From 117d45ea9fbb74158cf1c2423bb095ff55bd1b0e Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Sun, 19 Apr 2026 19:07:03 +0200 Subject: [PATCH 01/45] testmask: read sources from Taskfile.yml Replace the hardcoded prefix table with parsing of Taskfile.yml so the list of paths that triggers each CI test target is derived from the test:exp-aitools, test:exp-ssh, and test:pipelines tasks' `sources:`. Also makes the tool CWD-independent via `git rev-parse --show-toplevel`. Co-authored-by: Isaac --- tools/go.mod | 6 +- tools/testmask/git.go | 9 +++ tools/testmask/main.go | 15 ++++- tools/testmask/targets.go | 101 +++++++++++++++++++++------------ tools/testmask/targets_test.go | 62 +++++--------------- 5 files changed, 108 insertions(+), 85 deletions(-) diff --git a/tools/go.mod b/tools/go.mod index 7dfc7a4ef4..644cafaec1 100644 --- a/tools/go.mod +++ b/tools/go.mod @@ -6,6 +6,11 @@ toolchain go1.25.9 require github.com/stretchr/testify v1.11.1 +require ( + github.com/stretchr/testify v1.11.1 + gopkg.in/yaml.v3 v3.0.1 +) + require ( 4d63.com/gocheckcompilerdirectives v1.3.0 // indirect 4d63.com/gochecknoglobals v0.2.2 // indirect @@ -215,7 +220,6 @@ require ( google.golang.org/protobuf v1.36.6 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect gotest.tools/gotestsum v1.12.1 // indirect honnef.co/go/tools v0.6.1 // indirect mvdan.cc/gofumpt v0.9.1 // indirect diff --git a/tools/testmask/git.go b/tools/testmask/git.go index 23c2592361..f803da4b38 100644 --- a/tools/testmask/git.go +++ b/tools/testmask/git.go @@ -23,3 +23,12 @@ func GetChangedFiles(headRef, baseRef string) ([]string, error) { return lines, nil } + +// GitRepoRoot returns the absolute path to the top-level directory of the git repo. +func GitRepoRoot() (string, error) { + output, err := exec.Command("git", "rev-parse", "--show-toplevel").Output() + if err != nil { + return "", fmt.Errorf("failed to find git repo root: %w", err) + } + return strings.TrimSpace(string(output)), nil +} diff --git a/tools/testmask/main.go b/tools/testmask/main.go index 6ef68df36a..dd71cbee5f 100644 --- a/tools/testmask/main.go +++ b/tools/testmask/main.go @@ -6,6 +6,7 @@ import ( "encoding/json" "fmt" "os" + "path/filepath" ) func main() { @@ -17,13 +18,25 @@ func main() { headRef := os.Args[1] baseRef := os.Args[2] + repoRoot, err := GitRepoRoot() + if err != nil { + fmt.Fprintf(os.Stderr, "Error finding repo root: %v\n", err) + os.Exit(1) + } + + mappings, err := LoadTargetMappings(filepath.Join(repoRoot, "Taskfile.yml")) + if err != nil { + fmt.Fprintf(os.Stderr, "Error loading target mappings: %v\n", err) + os.Exit(1) + } + changedFiles, err := GetChangedFiles(headRef, baseRef) if err != nil { fmt.Fprintf(os.Stderr, "Error getting changed files: %v\n", err) os.Exit(1) } - targets := GetTargets(changedFiles) + targets := GetTargets(changedFiles, mappings) err = json.NewEncoder(os.Stdout).Encode(targets) if err != nil { fmt.Fprintf(os.Stderr, "Error encoding targets: %v\n", err) diff --git a/tools/testmask/targets.go b/tools/testmask/targets.go index f4566ea7d4..1e49192e3c 100644 --- a/tools/testmask/targets.go +++ b/tools/testmask/targets.go @@ -1,14 +1,21 @@ package main import ( + "fmt" "maps" + "os" "slices" "strings" + + "gopkg.in/yaml.v3" ) -type targetMapping struct { - prefixes []string - target string +// ciTargetTasks maps the dash-separated output name used by CI to the +// colon-separated Taskfile task name whose `sources:` define its trigger set. +var ciTargetTasks = map[string]string{ + "test-exp-aitools": "test:exp-aitools", + "test-exp-ssh": "test:exp-ssh", + "test-pipelines": "test:pipelines", } // commonTriggerPatterns lists patterns that trigger all test targets. @@ -18,44 +25,70 @@ var commonTriggerPatterns = []string{ ".github/actions/setup-build-environment/", } -var fileTargetMappings = []targetMapping{ - { - prefixes: slices.Concat(commonTriggerPatterns, []string{ - // Specify files that match targets below and should still trigger the "test" target. - }), - target: "test", - }, - { - prefixes: slices.Concat(commonTriggerPatterns, []string{ - "experimental/aitools/", - }), - target: "test-exp-aitools", - }, - { - prefixes: slices.Concat(commonTriggerPatterns, []string{ - "experimental/ssh/", - "acceptance/ssh/", - }), - target: "test-exp-ssh", - }, - { - prefixes: slices.Concat(commonTriggerPatterns, []string{ - "cmd/pipelines/", - "acceptance/pipelines/", - }), - target: "test-pipelines", - }, +type targetMapping struct { + prefixes []string + target string +} + +type taskfile struct { + Tasks map[string]taskfileTask `yaml:"tasks"` +} + +type taskfileTask struct { + Sources []string `yaml:"sources"` +} + +// LoadTargetMappings reads Taskfile.yml and builds target mappings for CI tasks +// by extracting `sources:` from each task listed in ciTargetTasks. +func LoadTargetMappings(taskfilePath string) ([]targetMapping, error) { + data, err := os.ReadFile(taskfilePath) + if err != nil { + return nil, fmt.Errorf("read %s: %w", taskfilePath, err) + } + var tf taskfile + if err := yaml.Unmarshal(data, &tf); err != nil { + return nil, fmt.Errorf("parse %s: %w", taskfilePath, err) + } + + mappings := []targetMapping{ + {prefixes: slices.Clone(commonTriggerPatterns), target: "test"}, + } + for _, outputName := range slices.Sorted(maps.Keys(ciTargetTasks)) { + taskName := ciTargetTasks[outputName] + t, ok := tf.Tasks[taskName] + if !ok { + return nil, fmt.Errorf("task %q not found in %s", taskName, taskfilePath) + } + if len(t.Sources) == 0 { + return nil, fmt.Errorf("task %q in %s has no sources", taskName, taskfilePath) + } + prefixes := slices.Clone(commonTriggerPatterns) + for _, src := range t.Sources { + prefixes = append(prefixes, sourceToPrefix(src)) + } + mappings = append(mappings, targetMapping{prefixes: prefixes, target: outputName}) + } + return mappings, nil +} + +// sourceToPrefix converts a Taskfile source glob like "dir/**" into a prefix +// suitable for strings.HasPrefix matching ("dir/"). +func sourceToPrefix(src string) string { + src = strings.TrimSuffix(src, "/**") + if !strings.HasSuffix(src, "/") { + src += "/" + } + return src } // GetTargets matches files to targets based on patterns and returns the matched targets. -func GetTargets(files []string) []string { +func GetTargets(files []string, mappings []targetMapping) []string { targetSet := make(map[string]bool) unmatchedFiles := []string{} for _, file := range files { - // Check all mappings for this file (a file can match multiple targets). matched := false - for _, mapping := range fileTargetMappings { + for _, mapping := range mappings { for _, prefix := range mapping.prefixes { if strings.HasPrefix(file, prefix) { targetSet[mapping.target] = true @@ -69,12 +102,10 @@ func GetTargets(files []string) []string { } } - // If there are unmatched files, add the "test" target to run all tests. if len(unmatchedFiles) > 0 { targetSet["test"] = true } - // If there are no targets, add the "test" target to run all tests. if len(targetSet) == 0 { return []string{"test"} } diff --git a/tools/testmask/targets_test.go b/tools/testmask/targets_test.go index 4ca347fb37..fe248d8d41 100644 --- a/tools/testmask/targets_test.go +++ b/tools/testmask/targets_test.go @@ -1,9 +1,6 @@ package main import ( - "os" - "regexp" - "strings" "testing" "github.com/stretchr/testify/assert" @@ -11,6 +8,9 @@ import ( ) func TestGetTargets(t *testing.T) { + mappings, err := LoadTargetMappings("../../Taskfile.yml") + require.NoError(t, err) + tests := []struct { name string files []string @@ -31,6 +31,13 @@ func TestGetTargets(t *testing.T) { }, targets: []string{"test-pipelines"}, }, + { + name: "acceptance_apps_triggers_aitools", + files: []string{ + "acceptance/apps/basic/script", + }, + targets: []string{"test-exp-aitools"}, + }, { name: "non_matching", files: []string{ @@ -77,54 +84,13 @@ func TestGetTargets(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - targets := GetTargets(tt.files) + targets := GetTargets(tt.files, mappings) assert.Equal(t, tt.targets, targets) }) } } -func TestTargetsExistInMakefile(t *testing.T) { - // Collect all targets from fileTargetMappings - expectedTargets := make(map[string]bool) - for _, mapping := range fileTargetMappings { - expectedTargets[mapping.target] = true - } - - // Also include "test" since it's used in GetTargets - expectedTargets["test"] = true - - // Read and parse Makefile to extract target names - makefileTargets := parseMakefileTargets(t, "../../Makefile") - - // Verify all expected targets exist in Makefile - var missingTargets []string - for target := range expectedTargets { - if !makefileTargets[target] { - missingTargets = append(missingTargets, target) - } - } - - if len(missingTargets) > 0 { - t.Errorf("The following targets are defined in targets.go but do not exist in Makefile: %v", missingTargets) - } -} - -// parseMakefileTargets parses a Makefile and returns a set of target names -func parseMakefileTargets(t *testing.T, makefilePath string) map[string]bool { - targets := make(map[string]bool) - targetRegex := regexp.MustCompile(`^([a-zA-Z0-9_-]+):`) - - content, err := os.ReadFile(makefilePath) - require.NoError(t, err) - - lines := strings.Split(string(content), "\n") - for _, line := range lines { - // Match Makefile target pattern: target: - matches := targetRegex.FindStringSubmatch(line) - if len(matches) > 1 { - targets[matches[1]] = true - } - } - - return targets +func TestLoadTargetMappingsMissingFile(t *testing.T) { + _, err := LoadTargetMappings("nonexistent.yml") + assert.Error(t, err) } From a4ace47bc9dcd52734e0ba00e3fe51332f62c750 Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Sun, 19 Apr 2026 19:11:13 +0200 Subject: [PATCH 02/45] Migrate build/test commands from Makefile to Taskfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce Taskfile.yml as the single source of truth for build, test, lint, format, and codegen commands. Provide a thin Makefile wrapper that forwards all targets to task so existing `make ` invocations keep working for single-word targets. Move python/Makefile into the same Taskfile under python:* tasks. Task is vendored via a separate tools/task module to avoid its charmbracelet dependencies conflicting with tools/go.mod (golangci-lint pins older charmbracelet versions). Also update acceptance test helper to build yamlfmt directly — the Makefile wrapper can no longer forward the old `tools/yamlfmt` target since it's now a Task-only dependency. Co-authored-by: Isaac --- .gitignore | 13 +- Makefile | 291 +--------------- Taskfile.yml | 619 ++++++++++++++++++++++++++++++++++ acceptance/acceptance_test.go | 6 +- python/Makefile | 38 --- tools/task/go.mod | 137 ++++++++ tools/task/go.sum | 309 +++++++++++++++++ 7 files changed, 1082 insertions(+), 331 deletions(-) create mode 100644 Taskfile.yml delete mode 100644 python/Makefile create mode 100644 tools/task/go.mod create mode 100644 tools/task/go.sum diff --git a/.gitignore b/.gitignore index b7c7726d93..6e0a29ed9e 100644 --- a/.gitignore +++ b/.gitignore @@ -28,17 +28,22 @@ __pycache__ .ruff_cache -# Test results from 'make test' +# Test results from 'task test' test-output.json +test-output-unit.json +test-output-acc.json -# Built by make for 'make fmt' and yamlcheck.py in acceptance tests +# Taskfile cache +.task/ + +# Built for 'task fmt' and yamlcheck.py in acceptance tests tools/yamlfmt tools/yamlfmt.exe -# Built by make for 'make lint' +# Built for 'task lint' tools/golangci-lint -# Built by make for test filtering +# Built for test filtering tools/testmask/testmask # Cache for tools/gh_report.py diff --git a/Makefile b/Makefile index c763496ceb..66e096d090 100644 --- a/Makefile +++ b/Makefile @@ -1,287 +1,4 @@ -.PHONY: default -default: checks fmt lint - -# Default packages to test (all) -TEST_PACKAGES = ./acceptance/internal ./libs/... ./internal/... ./cmd/... ./bundle/... ./experimental/ssh/... . - -# Default acceptance test filter (all) -ACCEPTANCE_TEST_FILTER = "" - -GO_TOOL ?= go tool -modfile=tools/go.mod -GOTESTSUM_FORMAT ?= pkgname-and-test-fails -GOTESTSUM_CMD ?= ${GO_TOOL} gotestsum --format ${GOTESTSUM_FORMAT} --no-summary=skipped --jsonfile test-output.json --rerun-fails -LOCAL_TIMEOUT ?= 30m - - -.PHONY: lintfull -lintfull: ./tools/golangci-lint - ./tools/golangci-lint run --fix - -.PHONY: lint -lint: ./tools/golangci-lint - ./tools/lintdiff.py ./tools/golangci-lint run --fix - -.PHONY: tidy -tidy: - @# not part of golangci-lint, apparently - go mod tidy - -.PHONY: lintcheck -lintcheck: ./tools/golangci-lint - ./tools/golangci-lint run ./... - -.PHONY: fmtfull -fmtfull: ./tools/golangci-lint ./tools/yamlfmt - ruff format -n - ./tools/golangci-lint fmt - ./tools/yamlfmt . - -.PHONY: fmt -fmt: ./tools/golangci-lint ./tools/yamlfmt - ruff format -n - ./tools/lintdiff.py ./tools/golangci-lint fmt - ./tools/yamlfmt . - -# pre-building yamlfmt because it is invoked from tests and scripts -tools/yamlfmt: tools/go.mod tools/go.sum - go build -modfile=tools/go.mod -o tools/yamlfmt github.com/google/yamlfmt/cmd/yamlfmt - -tools/yamlfmt.exe: tools/go.mod tools/go.sum - go build -modfile=tools/go.mod -o tools/yamlfmt.exe github.com/google/yamlfmt/cmd/yamlfmt - -# pre-building golangci-lint because it's faster to run pre-built version -tools/golangci-lint: tools/go.mod tools/go.sum - go build -modfile=tools/go.mod -o tools/golangci-lint github.com/golangci/golangci-lint/v2/cmd/golangci-lint - -.PHONY: ws -ws: - ./tools/validate_whitespace.py - -.PHONY: wsfix -wsfix: - ./tools/validate_whitespace.py --fix - -.PHONY: links -links: - ./tools/update_github_links.py - -# Checks other than 'fmt' and 'lint'; these are fast, so can be run first -.PHONY: checks -checks: tidy ws links - - -.PHONY: install-pythons -install-pythons: - uv python install 3.9 3.10 3.11 3.12 3.13 - -.PHONY: test -test: test-unit test-acc - -.PHONY: test-unit -test-unit: - ${GOTESTSUM_CMD} --packages "${TEST_PACKAGES}" -- -timeout=${LOCAL_TIMEOUT} - -.PHONY: test-acc -test-acc: - ${GOTESTSUM_CMD} --packages ./acceptance/... -- -timeout=${LOCAL_TIMEOUT} -run ${ACCEPTANCE_TEST_FILTER} - -# Updates acceptance test output (local tests) -.PHONY: test-update -test-update: - -go test ./acceptance -run '^TestAccept$$' -update -timeout=${LOCAL_TIMEOUT} - -# Updates acceptance test output for template tests only -.PHONY: test-update-templates -test-update-templates: - -go test ./acceptance -run '^TestAccept/bundle/templates' -update -timeout=${LOCAL_TIMEOUT} - -# Regenerate out.test.toml files without running tests -.PHONY: generate-out-test-toml -generate-out-test-toml: - go test ./acceptance -run '^TestAccept$$' -only-out-test-toml -timeout=${LOCAL_TIMEOUT} - -# Updates acceptance test output (integration tests, requires access) -.PHONY: test-update-aws -test-update-aws: - deco env run -i -n aws-prod-ucws -- env DATABRICKS_TEST_SKIPLOCAL=1 go test ./acceptance -run ^TestAccept$$ -update -timeout=1h -v - -.PHONY: test-update-all -test-update-all: test-update test-update-aws - -.PHONY: slowest -slowest: - ${GO_TOOL} gotestsum tool slowest --jsonfile test-output.json --threshold 1s --num 50 - -.PHONY: cover -cover: - rm -fr ./acceptance/build/cover/ - VERBOSE_TEST=1 ${GOTESTSUM_CMD} --packages "${TEST_PACKAGES}" -- -coverprofile=coverage.txt -timeout=${LOCAL_TIMEOUT} - VERBOSE_TEST=1 CLI_GOCOVERDIR=build/cover ${GOTESTSUM_CMD} --packages ./acceptance/... -- -timeout=${LOCAL_TIMEOUT} -run ${ACCEPTANCE_TEST_FILTER} - rm -fr ./acceptance/build/cover-merged/ - mkdir -p acceptance/build/cover-merged/ - go tool covdata merge -i $$(printf '%s,' acceptance/build/cover/* | sed 's/,$$//') -o acceptance/build/cover-merged/ - go tool covdata textfmt -i acceptance/build/cover-merged -o coverage-acceptance.txt - -.PHONY: showcover -showcover: - go tool cover -html=coverage.txt - -.PHONY: acc-showcover -acc-showcover: - go tool cover -html=coverage-acceptance.txt - -.PHONY: build -build: tidy - go build - -# builds the binary in a VM environment (such as Parallels Desktop) where your files are mirrored from the host os -.PHONY: build-vm -build-vm: tidy - go build -buildvcs=false - -.PHONY: snapshot -snapshot: - go build -o .databricks/databricks - -# Produce release binaries and archives in the dist folder without uploading them anywhere. -# Useful for "databricks ssh" development, as it needs to upload linux releases to the /Workspace. -.PHONY: snapshot-release -snapshot-release: - goreleaser release --clean --skip docker --snapshot - -.PHONY: schema -schema: - go run ./bundle/internal/schema ./bundle/internal/schema ./bundle/schema/jsonschema.json - -.PHONY: schema-for-docs -schema-for-docs: - go run ./bundle/internal/schema ./bundle/internal/schema ./bundle/schema/jsonschema_for_docs.json --docs - -.PHONY: docs -docs: - go run ./bundle/docsgen ./bundle/internal/schema ./bundle/docsgen - -INTEGRATION = go run -modfile=tools/go.mod ./tools/testrunner/main.go ${GO_TOOL} gotestsum --format github-actions --rerun-fails --jsonfile output.json --packages "./acceptance ./integration/..." -- -parallel 4 -timeout=2h - -.PHONY: integration -integration: install-pythons - $(INTEGRATION) - -.PHONY: integration-short -integration-short: install-pythons - DATABRICKS_TEST_SKIPLOCAL=1 VERBOSE_TEST=1 $(INTEGRATION) -short - -.PHONY: dbr-integration -dbr-integration: install-pythons - DBR_ENABLED=true go test -v -timeout 4h -run TestDbrAcceptance$$ ./acceptance - -# DBR acceptance tests - run on Databricks Runtime using serverless compute -# These require deco env run for authentication -# Set DBR_TEST_VERBOSE=1 for detailed output (e.g., DBR_TEST_VERBOSE=1 make dbr-test) -.PHONY: dbr-test -dbr-test: - deco env run -i -n aws-prod-ucws -- make dbr-integration - -.PHONY: generate-validation -generate-validation: - go run ./bundle/internal/validation/. - gofmt -w -s ./bundle/internal/validation/generated - -# Rule to generate the CLI from a new version of the OpenAPI spec. -# I recommend running this rule from Arca because of faster build times -# because of better caching and beefier machines, but it should also work -# fine from your local mac. -# -# By default, this rule will use the universe directory in your home -# directory. You can override this by setting the UNIVERSE_DIR -# environment variable. -# -# Example: -# UNIVERSE_DIR=/Users/shreyas.goenka/universe make generate -UNIVERSE_DIR ?= $(HOME)/universe -GENKIT_BINARY := $(UNIVERSE_DIR)/bazel-bin/openapi/genkit/genkit_/genkit - -.PHONY: generate -generate: - @echo "Checking out universe at SHA: $$(cat .codegen/_openapi_sha)" - cd $(UNIVERSE_DIR) && git cat-file -e $$(cat $(PWD)/.codegen/_openapi_sha) 2>/dev/null || git fetch --filter=blob:none origin master && git checkout $$(cat $(PWD)/.codegen/_openapi_sha) - @echo "Building genkit..." - cd $(UNIVERSE_DIR) && bazel build //openapi/genkit - @echo "Generating CLI code..." - $(GENKIT_BINARY) update-sdk - cat .gitattributes.manual .gitattributes > .gitattributes.tmp && mv .gitattributes.tmp .gitattributes - -go test ./acceptance -run TestAccept/bundle/refschema -update &> /dev/null - @echo "Updating direct engine config..." - make generate-direct - go test ./bundle/internal/schema - -.codegen/openapi.json: .codegen/_openapi_sha - wget -O $@.tmp "https://openapi.dev.databricks.com/$$(cat $<)/specs/all-internal.json" && mv $@.tmp $@ && touch $@ - -.PHONY: generate-direct -generate-direct: generate-direct-apitypes generate-direct-resources - -.PHONY: generate-direct-apitypes -generate-direct-apitypes: bundle/direct/dresources/apitypes.generated.yml - -.PHONY: generate-direct-resources -generate-direct-resources: bundle/direct/dresources/resources.generated.yml - -.PHONY: generate-direct-clean -generate-direct-clean: - rm -f bundle/direct/dresources/apitypes.generated.yml bundle/direct/dresources/resources.generated.yml - -bundle/direct/dresources/apitypes.generated.yml: ./bundle/direct/tools/generate_apitypes.py .codegen/openapi.json acceptance/bundle/refschema/out.fields.txt - python3 $^ > $@ - -bundle/direct/dresources/resources.generated.yml: ./bundle/direct/tools/generate_resources.py .codegen/openapi.json bundle/direct/dresources/apitypes.generated.yml bundle/direct/dresources/apitypes.yml acceptance/bundle/refschema/out.fields.txt - python3 $^ > $@ - -.PHONY: test-exp-aitools -test-exp-aitools: - make test TEST_PACKAGES="./experimental/aitools/..." ACCEPTANCE_TEST_FILTER="TestAccept/apps" - -.PHONY: test-exp-ssh -test-exp-ssh: - make test TEST_PACKAGES="./experimental/ssh/..." ACCEPTANCE_TEST_FILTER="TestAccept/ssh" - -.PHONY: test-pipelines -test-pipelines: - make test TEST_PACKAGES="./cmd/pipelines/..." ACCEPTANCE_TEST_FILTER="TestAccept/pipelines" - - -# Benchmarks: - -.PHONY: bench1k -bench1k: - BENCHMARK_PARAMS="--jobs 1000" go test ./acceptance -v -tail -run TestAccept/bundle/benchmarks -timeout=120m - -.PHONY: bench100 -bench100: - BENCHMARK_PARAMS="--jobs 100" go test ./acceptance -v -tail -run TestAccept/bundle/benchmarks -timeout=120m - -# small benchmark to quickly test benchmark-related code -.PHONY: bench10 -bench10: - BENCHMARK_PARAMS="--jobs 10" go test ./acceptance -v -tail -run TestAccept/bundle/benchmarks -timeout=120m - -bench1k.log: - make bench1k | tee $@ - -bench100.log: - make bench100 | tee $@ - -bench10.log: - make bench10 | tee $@ - -.PHONY: bench1k_summary -bench1k_summary: bench1k.log - ./tools/bench_parse.py $< - -.PHONY: bench100_summary -bench100_summary: bench100.log - ./tools/bench_parse.py $< - -.PHONY: bench10_summary -bench10_summary: bench10.log - ./tools/bench_parse.py $< +TASK := go tool -modfile=tools/task/go.mod task +.PHONY: $(MAKECMDGOALS) +%: + @$(TASK) "$@" diff --git a/Taskfile.yml b/Taskfile.yml new file mode 100644 index 0000000000..4d9b23986b --- /dev/null +++ b/Taskfile.yml @@ -0,0 +1,619 @@ +version: '3' + +vars: + GO_TOOL: go tool -modfile=tools/go.mod + TEST_PACKAGES: ./acceptance/internal ./libs/... ./internal/... ./cmd/... ./bundle/... ./experimental/ssh/... . + ACCEPTANCE_TEST_FILTER: "" + MERGE_BASE: + sh: git merge-base main HEAD + +tasks: + default: + desc: Run all checks, fmt, lint, tests, and regeneration + cmds: + - task: checks + - task: fmt:full + - task: lint:full + - task: test + - task: schema + - task: generate:validation + - task: python:lint + - task: python:test + + # --- Tool binaries (for acceptance tests that call them by path) --- + + _build-yamlfmt: + internal: true + sources: + - tools/go.mod + - tools/go.sum + generates: + - tools/yamlfmt + cmds: + - go build -modfile=tools/go.mod -o tools/yamlfmt github.com/google/yamlfmt/cmd/yamlfmt + + # --- Linting --- + + lint: + desc: Lint changed Go files (root module, diff against main) + sources: + - "**/*.go" + - .golangci.yaml + cmds: + - ./tools/lintdiff.py go tool -modfile=tools/go.mod golangci-lint run --fix + + lint:full: + desc: Lint all Go files with fixes (root module) + sources: + - "**/*.go" + - .golangci.yaml + cmds: + - go tool -modfile=tools/go.mod golangci-lint run --fix + + lint:check: + desc: Lint all Go files without fixes (root module) + sources: + - "**/*.go" + - .golangci.yaml + cmds: + - go tool -modfile=tools/go.mod golangci-lint run ./... + + lint:tools: + desc: Lint tools/ module + dir: tools + sources: + - "**/*.go" + cmds: + - go tool -modfile={{.ROOT_DIR}}/tools/go.mod golangci-lint run ./... + + lint:codegen: + desc: Lint bundle/internal/tf/codegen module + dir: bundle/internal/tf/codegen + sources: + - "**/*.go" + cmds: + - go tool -modfile={{.ROOT_DIR}}/tools/go.mod golangci-lint run ./... + + # --- Formatting --- + + fmt: + desc: Format changed files (Python, Go, YAML; diff against main) + cmds: + - ruff format -n + - ./tools/lintdiff.py go tool -modfile=tools/go.mod golangci-lint fmt + - go tool -modfile=tools/go.mod yamlfmt . + + fmt:full: + desc: Format all files (Python, Go, YAML) + cmds: + - ruff format -n + - go tool -modfile=tools/go.mod golangci-lint fmt + - go tool -modfile=tools/go.mod yamlfmt . + + # --- Code checks --- + + tidy: + desc: Run go mod tidy + sources: + - go.mod + - go.sum + - "**/*.go" + cmds: + - go mod tidy + + ws: + desc: Check whitespace + sources: + - "**/*.go" + - "**/*.py" + - "**/*.yml" + - "**/*.yaml" + - "**/*.md" + cmds: + - ./tools/validate_whitespace.py + + ws:fix: + desc: Fix whitespace issues + cmds: + - ./tools/validate_whitespace.py --fix + + links: + desc: Update GitHub links in docs + sources: + - "**/*.md" + cmds: + - ./tools/update_github_links.py + + checks: + desc: Run quick checks (tidy, whitespace, links) + deps: [tidy, ws, links] + + install-pythons: + desc: Install Python 3.9-3.13 via uv + cmds: + - uv python install 3.9 3.10 3.11 3.12 3.13 + + # --- Building --- + + build: + desc: Build the CLI binary + deps: [tidy] + sources: + - "**/*.go" + - go.mod + - go.sum + generates: + - databricks + cmds: + - go build + + build:vm: + desc: Build in VM environment (no VCS stamping) + deps: [tidy] + sources: + - "**/*.go" + cmds: + - go build -buildvcs=false + + snapshot: + desc: Build snapshot binary to .databricks/databricks + cmds: + - go build -o .databricks/databricks + + snapshot:release: + desc: Build release binaries locally without uploading + cmds: + - goreleaser release --clean --skip docker --snapshot + + # --- Testing --- + + test: + desc: Run short unit and acceptance tests (in parallel) + deps: + - task: test:unit + vars: + TEST_PACKAGES: "{{.TEST_PACKAGES}}" + - task: test:acc + vars: + ACCEPTANCE_TEST_FILTER: "{{.ACCEPTANCE_TEST_FILTER}}" + cmds: + - cat test-output-unit.json test-output-acc.json > test-output.json + + test:slow: + desc: Run all unit and acceptance tests (in parallel, no -short) + deps: + - task: test:slow-unit + vars: + TEST_PACKAGES: "{{.TEST_PACKAGES}}" + - task: test:slow-acc + vars: + ACCEPTANCE_TEST_FILTER: "{{.ACCEPTANCE_TEST_FILTER}}" + cmds: + - cat test-output-unit.json test-output-acc.json > test-output.json + + test:unit: + desc: Run short unit tests + sources: + - "**/*.go" + vars: + TEST_PACKAGES: '{{.TEST_PACKAGES | default "./acceptance/internal ./libs/... ./internal/... ./cmd/... ./bundle/... ./experimental/ssh/... ."}}' + cmds: + - | + {{.GO_TOOL}} gotestsum \ + --format ${GOTESTSUM_FORMAT:-pkgname-and-test-fails} \ + --no-summary=skipped \ + --jsonfile test-output-unit.json \ + --rerun-fails \ + --packages "{{.TEST_PACKAGES}}" \ + -- -timeout=${LOCAL_TIMEOUT:-30m} -short + + test:slow-unit: + desc: Run all unit tests (no -short) + sources: + - "**/*.go" + vars: + TEST_PACKAGES: '{{.TEST_PACKAGES | default "./acceptance/internal ./libs/... ./internal/... ./cmd/... ./bundle/... ./experimental/ssh/... ."}}' + cmds: + - | + {{.GO_TOOL}} gotestsum \ + --format ${GOTESTSUM_FORMAT:-pkgname-and-test-fails} \ + --no-summary=skipped \ + --jsonfile test-output-unit.json \ + --rerun-fails \ + --packages "{{.TEST_PACKAGES}}" \ + -- -timeout=${LOCAL_TIMEOUT:-30m} + + test:acc: + desc: Run short acceptance tests + sources: + - "**/*.go" + - acceptance/** + vars: + ACCEPTANCE_TEST_FILTER: '{{.ACCEPTANCE_TEST_FILTER | default ""}}' + cmds: + - | + {{.GO_TOOL}} gotestsum \ + --format ${GOTESTSUM_FORMAT:-pkgname-and-test-fails} \ + --no-summary=skipped \ + --jsonfile test-output-acc.json \ + --rerun-fails \ + --packages ./acceptance/... \ + -- -timeout=${LOCAL_TIMEOUT:-30m} -short{{if .ACCEPTANCE_TEST_FILTER}} -run "{{.ACCEPTANCE_TEST_FILTER}}"{{end}} + + test:slow-acc: + desc: Run all acceptance tests (no -short) + sources: + - "**/*.go" + - acceptance/** + vars: + ACCEPTANCE_TEST_FILTER: '{{.ACCEPTANCE_TEST_FILTER | default ""}}' + cmds: + - | + {{.GO_TOOL}} gotestsum \ + --format ${GOTESTSUM_FORMAT:-pkgname-and-test-fails} \ + --no-summary=skipped \ + --jsonfile test-output-acc.json \ + --rerun-fails \ + --packages ./acceptance/... \ + -- -timeout=${LOCAL_TIMEOUT:-30m}{{if .ACCEPTANCE_TEST_FILTER}} -run "{{.ACCEPTANCE_TEST_FILTER}}"{{end}} + + test:update: + desc: Update acceptance test output (local) + cmds: + - "-go test ./acceptance -run '^TestAccept$' -update -timeout=${LOCAL_TIMEOUT:-30m}" + + test:update-templates: + desc: Update acceptance test template output + cmds: + - "-go test ./acceptance -run '^TestAccept/bundle/templates' -update -timeout=${LOCAL_TIMEOUT:-30m}" + + test:update-aws: + desc: Update acceptance test output (integration, requires deco access) + cmds: + - "deco env run -i -n aws-prod-ucws -- env DATABRICKS_TEST_SKIPLOCAL=1 go test ./acceptance -run ^TestAccept$ -update -timeout=1h -v" + + test:update-all: + desc: Update all acceptance test outputs + deps: ['test:update', 'test:update-aws'] + + generate:out-test-toml: + desc: Regenerate out.test.toml files without running tests + cmds: + - "go test ./acceptance -run '^TestAccept$' -only-out-test-toml -timeout=${LOCAL_TIMEOUT:-30m}" + + slowest: + desc: Show 50 slowest tests from last run + cmds: + - "{{.GO_TOOL}} gotestsum tool slowest --jsonfile test-output.json --threshold 1s --num 50" + + cover: + desc: Run tests with coverage + vars: + ACCEPTANCE_TEST_FILTER: '{{.ACCEPTANCE_TEST_FILTER | default ""}}' + TEST_PACKAGES: '{{.TEST_PACKAGES | default "./acceptance/internal ./libs/... ./internal/... ./cmd/... ./bundle/... ./experimental/ssh/... ."}}' + cmds: + - rm -fr ./acceptance/build/cover/ + - | + VERBOSE_TEST=1 {{.GO_TOOL}} gotestsum \ + --format ${GOTESTSUM_FORMAT:-pkgname-and-test-fails} \ + --no-summary=skipped \ + --jsonfile test-output.json \ + --rerun-fails \ + --packages "{{.TEST_PACKAGES}}" \ + -- -coverprofile=coverage.txt -timeout=${LOCAL_TIMEOUT:-30m} + - | + VERBOSE_TEST=1 CLI_GOCOVERDIR=build/cover {{.GO_TOOL}} gotestsum \ + --format ${GOTESTSUM_FORMAT:-pkgname-and-test-fails} \ + --no-summary=skipped \ + --jsonfile test-output.json \ + --rerun-fails \ + --packages ./acceptance/... \ + -- -timeout=${LOCAL_TIMEOUT:-30m}{{if .ACCEPTANCE_TEST_FILTER}} -run "{{.ACCEPTANCE_TEST_FILTER}}"{{end}} + - rm -fr ./acceptance/build/cover-merged/ + - mkdir -p acceptance/build/cover-merged/ + - "go tool covdata merge -i $(printf '%s,' acceptance/build/cover/* | sed 's/,$//') -o acceptance/build/cover-merged/" + - go tool covdata textfmt -i acceptance/build/cover-merged -o coverage-acceptance.txt + + showcover: + desc: Open unit test coverage report in browser + cmds: + - go tool cover -html=coverage.txt + + showcover:acc: + desc: Open acceptance test coverage report in browser + cmds: + - go tool cover -html=coverage-acceptance.txt + + # --- Specialized test suites --- + + # The `sources:` on each test:* subproject target is the single source of truth for: + # 1. Taskfile's own checksum-based caching (skip re-run if nothing changed) + # 2. CI triggering — tools/testmask reads these sources to decide which CI jobs to run + # Keep patterns narrow and specific. Changes to files outside these paths trigger the + # generic `test` target (the catch-all) instead. + + test:exp-aitools: + desc: Run experimental aitools unit and acceptance tests (in parallel) + sources: + - experimental/aitools/** + - acceptance/apps/** + deps: + - task: test:unit + vars: + TEST_PACKAGES: ./experimental/aitools/... + - task: test:acc + vars: + ACCEPTANCE_TEST_FILTER: TestAccept/apps + cmds: + - cat test-output-unit.json test-output-acc.json > test-output.json + + test:exp-ssh: + desc: Run experimental SSH unit and acceptance tests (in parallel) + sources: + - experimental/ssh/** + - acceptance/ssh/** + deps: + - task: test:unit + vars: + TEST_PACKAGES: ./experimental/ssh/... + - task: test:acc + vars: + ACCEPTANCE_TEST_FILTER: TestAccept/ssh + cmds: + - cat test-output-unit.json test-output-acc.json > test-output.json + + test:pipelines: + desc: Run pipelines unit and acceptance tests (in parallel) + sources: + - cmd/pipelines/** + - acceptance/pipelines/** + deps: + - task: test:unit + vars: + TEST_PACKAGES: ./cmd/pipelines/... + - task: test:acc + vars: + ACCEPTANCE_TEST_FILTER: TestAccept/pipelines + cmds: + - cat test-output-unit.json test-output-acc.json > test-output.json + + # --- Integration tests --- + + integration: + desc: Run integration tests (requires Databricks workspace) + deps: [install-pythons] + cmds: + - | + go run -modfile=tools/go.mod ./tools/testrunner/main.go \ + {{.GO_TOOL}} gotestsum \ + --format github-actions \ + --rerun-fails \ + --jsonfile output.json \ + --packages "./acceptance ./integration/..." \ + -- -parallel 4 -timeout=2h + + integration:short: + desc: Run short integration tests + deps: [install-pythons] + cmds: + - | + DATABRICKS_TEST_SKIPLOCAL=1 VERBOSE_TEST=1 \ + go run -modfile=tools/go.mod ./tools/testrunner/main.go \ + {{.GO_TOOL}} gotestsum \ + --format github-actions \ + --rerun-fails \ + --jsonfile output.json \ + --packages "./acceptance ./integration/..." \ + -- -parallel 4 -timeout=2h -short + + dbr:integration: + desc: Run DBR acceptance tests on Databricks Runtime + deps: [install-pythons] + cmds: + - "DBR_ENABLED=true go test -v -timeout 4h -run TestDbrAcceptance$ ./acceptance" + + dbr:test: + desc: Run DBR tests via deco env (requires deco + aws-prod-ucws access) + cmds: + - "deco env run -i -n aws-prod-ucws -- go tool -modfile=tools/go.mod task dbr:integration" + + # --- Code generation --- + + schema: + desc: Generate bundle JSON schema (skipped if schema sources unchanged vs merge base) + status: + - git diff --quiet {{.MERGE_BASE}} -- bundle/internal/schema/ + - test -f bundle/schema/jsonschema.json + cmds: + - go run ./bundle/internal/schema ./bundle/internal/schema ./bundle/schema/jsonschema.json + + schema:for-docs: + desc: Generate bundle JSON schema for documentation + cmds: + - go run ./bundle/internal/schema ./bundle/internal/schema ./bundle/schema/jsonschema_for_docs.json --docs + + docs: + desc: Generate bundle documentation + cmds: + - go run ./bundle/docsgen ./bundle/internal/schema ./bundle/docsgen + + generate:validation: + desc: Generate enum and required field validation code (skipped if sources unchanged vs merge base) + status: + - git diff --quiet {{.MERGE_BASE}} -- bundle/internal/validation/ + - test -d bundle/internal/validation/generated + cmds: + - go run ./bundle/internal/validation/. + - gofmt -w -s ./bundle/internal/validation/generated + + generate:direct: + desc: Generate direct engine config (apitypes + resources) + deps: ['generate:direct-apitypes', 'generate:direct-resources'] + + generate:direct-apitypes: + deps: ['codegen:openapi-json'] + sources: + - bundle/direct/tools/generate_apitypes.py + - .codegen/openapi.json + - acceptance/bundle/refschema/out.fields.txt + generates: + - bundle/direct/dresources/apitypes.generated.yml + cmds: + - > + python3 bundle/direct/tools/generate_apitypes.py + .codegen/openapi.json + acceptance/bundle/refschema/out.fields.txt + > bundle/direct/dresources/apitypes.generated.yml + + generate:direct-resources: + deps: ['generate:direct-apitypes'] + sources: + - bundle/direct/tools/generate_resources.py + - .codegen/openapi.json + - bundle/direct/dresources/apitypes.generated.yml + - bundle/direct/dresources/apitypes.yml + - acceptance/bundle/refschema/out.fields.txt + generates: + - bundle/direct/dresources/resources.generated.yml + cmds: + - > + python3 bundle/direct/tools/generate_resources.py + .codegen/openapi.json + bundle/direct/dresources/apitypes.generated.yml + bundle/direct/dresources/apitypes.yml + acceptance/bundle/refschema/out.fields.txt + > bundle/direct/dresources/resources.generated.yml + + generate:direct-clean: + desc: Remove generated direct engine files + cmds: + - rm -f bundle/direct/dresources/apitypes.generated.yml bundle/direct/dresources/resources.generated.yml + + generate: + desc: Generate CLI code from OpenAPI spec (requires universe repo) + vars: + UNIVERSE_DIR: + sh: echo "${UNIVERSE_DIR:-$HOME/universe}" + cmds: + - | + echo "Checking out universe at SHA: $(cat .codegen/_openapi_sha)" + cd {{.UNIVERSE_DIR}} && \ + git cat-file -e $(cat {{.ROOT_DIR}}/.codegen/_openapi_sha) 2>/dev/null || \ + (git fetch --filter=blob:none origin master && \ + git checkout $(cat {{.ROOT_DIR}}/.codegen/_openapi_sha)) + - echo "Building genkit..." + - cd {{.UNIVERSE_DIR}} && bazel build //openapi/genkit + - echo "Generating CLI code..." + - "{{.UNIVERSE_DIR}}/bazel-bin/openapi/genkit/genkit_/genkit update-sdk" + - "cat .gitattributes.manual .gitattributes > .gitattributes.tmp && mv .gitattributes.tmp .gitattributes" + - "-go test ./acceptance -run TestAccept/bundle/refschema -update &> /dev/null" + - echo "Updating direct engine config..." + - task: generate:direct + - go test ./bundle/internal/schema + + codegen:openapi-json: + desc: Download OpenAPI spec (triggered by _openapi_sha change) + sources: + - .codegen/_openapi_sha + generates: + - .codegen/openapi.json + cmds: + - "wget -O .codegen/openapi.json.tmp \"https://openapi.dev.databricks.com/$(cat .codegen/_openapi_sha)/specs/all-internal.json\" && mv .codegen/openapi.json.tmp .codegen/openapi.json" + + # --- Python --- + + python:test: + desc: Run Python tests + dir: python + sources: + - "**/*.py" + cmds: + - uv run python -m pytest databricks_tests --cov=databricks.bundles --cov-report html -vv + + python:lint: + desc: Run Python lint checks + dir: python + sources: + - "**/*.py" + - pyproject.toml + - uv.lock + cmds: + - uv lock --check + - uv run ruff check databricks databricks_tests + - uv run pyright + - uv run ruff format --diff databricks databricks_tests + + python:fmt: + desc: Format Python code + dir: python + sources: + - "**/*.py" + cmds: + - uv run ruff check --fix databricks databricks_tests || true + - uv run ruff format + + python:docs: + desc: Generate Python documentation + dir: python + sources: + - "**/*.py" + cmds: + - uv run --python 3.12 sphinx-build docs docs/_output --show-traceback --nitpicky --fresh-env --keep-going + + python:codegen: + desc: Run Python codegen + dir: python + sources: + - codegen/** + cmds: + - | + find databricks/bundles -type d -mindepth 1 -maxdepth 1 \ + ! -path databricks/bundles/core \ + ! -path databricks/bundles/resources \ + -exec rm -rf {} \; + - cd codegen && uv run -m pytest codegen_tests + - cd codegen && uv run -m codegen.main --output .. + - uv run ruff check --fix databricks databricks_tests || true + - uv run ruff format + + python:build: + desc: Build Python wheel + dir: python + cmds: + - rm -rf build dist + - uv build . + + # --- Benchmarks --- + + bench:1k: + desc: Benchmark with 1000 jobs + cmds: + - 'BENCHMARK_PARAMS="--jobs 1000" go test ./acceptance -v -tail -run TestAccept/bundle/benchmarks -timeout=120m | tee bench1k.log' + + bench:100: + desc: Benchmark with 100 jobs + cmds: + - 'BENCHMARK_PARAMS="--jobs 100" go test ./acceptance -v -tail -run TestAccept/bundle/benchmarks -timeout=120m | tee bench100.log' + + bench:10: + desc: Benchmark with 10 jobs (quick) + cmds: + - 'BENCHMARK_PARAMS="--jobs 10" go test ./acceptance -v -tail -run TestAccept/bundle/benchmarks -timeout=120m | tee bench10.log' + + bench:1k-summary: + desc: Run 1k benchmark and print summary + cmds: + - task: bench:1k + - ./tools/bench_parse.py bench1k.log + + bench:100-summary: + desc: Run 100 benchmark and print summary + cmds: + - task: bench:100 + - ./tools/bench_parse.py bench100.log + + bench:10-summary: + desc: Run 10 benchmark and print summary + cmds: + - task: bench:10 + - ./tools/bench_parse.py bench10.log diff --git a/acceptance/acceptance_test.go b/acceptance/acceptance_test.go index 7b8cf95258..5e28108532 100644 --- a/acceptance/acceptance_test.go +++ b/acceptance/acceptance_test.go @@ -1473,9 +1473,11 @@ func prepareWheelBuildDirectory(t *testing.T, dir string) string { } func BuildYamlfmt(t *testing.T) { - // Using make here instead of "go build" directly cause it's faster when it's already built args := []string{ - "make", "-s", "tools/yamlfmt" + exeSuffix, + "go", "build", + "-modfile=tools/go.mod", + "-o", "tools/yamlfmt" + exeSuffix, + "github.com/google/yamlfmt/cmd/yamlfmt", } RunCommand(t, args, "..", []string{}) } diff --git a/python/Makefile b/python/Makefile deleted file mode 100644 index be0fe664c0..0000000000 --- a/python/Makefile +++ /dev/null @@ -1,38 +0,0 @@ -sources = databricks databricks_tests - -fmt: - uv run ruff check --fix $(sources) || true - uv run ruff format - -docs: - # Python 3.12+ is needed for get_overloads - uv run --python 3.12 sphinx-build docs docs/_output --show-traceback --nitpicky --fresh-env --keep-going - -lint: - # check if lock matches the project metadata - uv lock --check - - uv run ruff check $(sources) - uv run pyright - uv run ruff format --diff - -codegen: - find databricks/bundles -type d -mindepth 1 -maxdepth 1 \ - ! -path databricks/bundles/core \ - ! -path databricks/bundles/resources \ - -exec rm -rf {} \; - - cd codegen; uv run -m pytest codegen_tests - cd codegen; uv run -m codegen.main --output .. - - uv run ruff check --fix $(sources) || true - uv run ruff format - -test: - uv run python -m pytest databricks_tests --cov=databricks.bundles --cov-report html -vv - -build: - rm -rf build dist - uv build . - -.PHONY: fmt docs lint codegen test build diff --git a/tools/task/go.mod b/tools/task/go.mod new file mode 100644 index 0000000000..1b9ef1ced6 --- /dev/null +++ b/tools/task/go.mod @@ -0,0 +1,137 @@ +module github.com/databricks/cli/tools/task + +go 1.25.0 + +toolchain go1.25.9 + +require ( + cel.dev/expr v0.24.0 // indirect + charm.land/bubbles/v2 v2.0.0 // indirect + charm.land/bubbletea/v2 v2.0.1 // indirect + charm.land/lipgloss/v2 v2.0.0 // indirect + cloud.google.com/go v0.123.0 // indirect + cloud.google.com/go/auth v0.17.0 // indirect + cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect + cloud.google.com/go/compute/metadata v0.9.0 // indirect + cloud.google.com/go/iam v1.5.3 // indirect + cloud.google.com/go/monitoring v1.24.2 // indirect + cloud.google.com/go/storage v1.58.0 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.29.0 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.54.0 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.54.0 // indirect + github.com/Ladicle/tabwriter v1.0.0 // indirect + github.com/Masterminds/semver/v3 v3.4.0 // indirect + github.com/alecthomas/chroma/v2 v2.23.1 // indirect + github.com/atotto/clipboard v0.1.4 // indirect + github.com/aws/aws-sdk-go-v2 v1.41.0 // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.4 // indirect + github.com/aws/aws-sdk-go-v2/config v1.32.6 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.19.6 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.16 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.16 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.16 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.16 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.7 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.16 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.16 // indirect + github.com/aws/aws-sdk-go-v2/service/s3 v1.95.0 // indirect + github.com/aws/aws-sdk-go-v2/service/signin v1.0.4 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.30.8 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.12 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.41.5 // indirect + github.com/aws/smithy-go v1.24.0 // indirect + github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/chainguard-dev/git-urls v1.0.2 // indirect + github.com/charmbracelet/colorprofile v0.4.2 // indirect + github.com/charmbracelet/ultraviolet v0.0.0-20260205113103-524a6607adb8 // indirect + github.com/charmbracelet/x/ansi v0.11.6 // indirect + github.com/charmbracelet/x/term v0.2.2 // indirect + github.com/charmbracelet/x/termios v0.1.1 // indirect + github.com/charmbracelet/x/windows v0.2.2 // indirect + github.com/clipperhouse/displaywidth v0.11.0 // indirect + github.com/clipperhouse/uax29/v2 v2.7.0 // indirect + github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/dlclark/regexp2 v1.11.5 // indirect + github.com/dominikbraun/graph v0.23.0 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect + github.com/elliotchance/orderedmap/v3 v3.1.0 // indirect + github.com/envoyproxy/go-control-plane/envoy v1.32.4 // indirect + github.com/envoyproxy/protoc-gen-validate v1.2.1 // indirect + github.com/fatih/color v1.18.0 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/fsnotify/fsnotify v1.9.0 // indirect + github.com/go-jose/go-jose/v4 v4.1.2 // indirect + github.com/go-logr/logr v1.4.3 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-task/slim-sprig/v3 v3.0.0 // indirect + github.com/go-task/task/v3 v3.49.1 // indirect + github.com/go-task/template v0.2.0 // indirect + github.com/google/s2a-go v0.1.9 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.7 // indirect + github.com/googleapis/gax-go/v2 v2.15.0 // indirect + github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.70 // indirect + github.com/hashicorp/go-cleanhttp v0.5.2 // indirect + github.com/hashicorp/go-getter v1.8.4 // indirect + github.com/hashicorp/go-version v1.8.0 // indirect + github.com/joho/godotenv v1.5.1 // indirect + github.com/klauspost/compress v1.18.2 // indirect + github.com/klauspost/cpuid/v2 v2.2.10 // indirect + github.com/klauspost/pgzip v1.2.6 // indirect + github.com/lucasb-eyer/go-colorful v1.3.0 // indirect + github.com/mattn/go-colorable v0.1.14 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-runewidth v0.0.20 // indirect + github.com/mitchellh/go-homedir v1.1.0 // indirect + github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect + github.com/muesli/cancelreader v0.2.2 // indirect + github.com/pierrec/lz4/v4 v4.1.22 // indirect + github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/puzpuzpuz/xsync/v4 v4.4.0 // indirect + github.com/rivo/uniseg v0.4.7 // indirect + github.com/sajari/fuzzy v1.0.0 // indirect + github.com/spf13/pflag v1.0.10 // indirect + github.com/spiffe/go-spiffe/v2 v2.5.0 // indirect + github.com/stretchr/objx v0.5.2 // indirect + github.com/stretchr/testify v1.11.1 // indirect + github.com/u-root/u-root v0.15.1-0.20251208185023-2f8c7e763cf8 // indirect + github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701 // indirect + github.com/ulikunitz/xz v0.5.15 // indirect + github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect + github.com/zeebo/errs v1.4.0 // indirect + github.com/zeebo/xxh3 v1.1.0 // indirect + go.opentelemetry.io/auto/sdk v1.2.1 // indirect + go.opentelemetry.io/contrib/detectors/gcp v1.36.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect + go.opentelemetry.io/otel v1.40.0 // indirect + go.opentelemetry.io/otel/metric v1.40.0 // indirect + go.opentelemetry.io/otel/sdk v1.40.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.40.0 // indirect + go.opentelemetry.io/otel/trace v1.40.0 // indirect + go.yaml.in/yaml/v3 v3.0.4 // indirect + golang.org/x/crypto v0.46.0 // indirect + golang.org/x/net v0.48.0 // indirect + golang.org/x/oauth2 v0.33.0 // indirect + golang.org/x/sync v0.19.0 // indirect + golang.org/x/sys v0.41.0 // indirect + golang.org/x/term v0.40.0 // indirect + golang.org/x/text v0.32.0 // indirect + golang.org/x/time v0.14.0 // indirect + google.golang.org/api v0.256.0 // indirect + google.golang.org/genproto v0.0.0-20250922171735-9219d122eba9 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20251111163417-95abcf5c77ba // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20251111163417-95abcf5c77ba // indirect + google.golang.org/grpc v1.76.0 // indirect + google.golang.org/protobuf v1.36.10 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + mvdan.cc/sh/moreinterp v0.0.0-20260120230322-19def062a997 // indirect + mvdan.cc/sh/v3 v3.12.1-0.20260124232039-e74afc18e65b // indirect +) + +tool github.com/go-task/task/v3/cmd/task diff --git a/tools/task/go.sum b/tools/task/go.sum new file mode 100644 index 0000000000..febb778ef7 --- /dev/null +++ b/tools/task/go.sum @@ -0,0 +1,309 @@ +cel.dev/expr v0.24.0 h1:56OvJKSH3hDGL0ml5uSxZmz3/3Pq4tJ+fb1unVLAFcY= +cel.dev/expr v0.24.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw= +charm.land/bubbles/v2 v2.0.0 h1:tE3eK/pHjmtrDiRdoC9uGNLgpopOd8fjhEe31B/ai5s= +charm.land/bubbles/v2 v2.0.0/go.mod h1:rCHoleP2XhU8um45NTuOWBPNVHxnkXKTiZqcclL/qOI= +charm.land/bubbletea/v2 v2.0.1 h1:B8e9zzK7x9JJ+XvHGF4xnYu9Xa0E0y0MyggY6dbaCfQ= +charm.land/bubbletea/v2 v2.0.1/go.mod h1:3LRff2U4WIYXy7MTxfbAQ+AdfM3D8Xuvz2wbsOD9OHQ= +charm.land/lipgloss/v2 v2.0.0 h1:sd8N/B3x892oiOjFfBQdXBQp3cAkvjGaU5TvVZC3ivo= +charm.land/lipgloss/v2 v2.0.0/go.mod h1:w6SnmsBFBmEFBodiEDurGS/sdUY/u1+v72DqUzc6J14= +cloud.google.com/go v0.123.0 h1:2NAUJwPR47q+E35uaJeYoNhuNEM9kM8SjgRgdeOJUSE= +cloud.google.com/go v0.123.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU= +cloud.google.com/go/auth v0.17.0 h1:74yCm7hCj2rUyyAocqnFzsAYXgJhrG26XCFimrc/Kz4= +cloud.google.com/go/auth v0.17.0/go.mod h1:6wv/t5/6rOPAX4fJiRjKkJCvswLwdet7G8+UGXt7nCQ= +cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc= +cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c= +cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= +cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= +cloud.google.com/go/iam v1.5.3 h1:+vMINPiDF2ognBJ97ABAYYwRgsaqxPbQDlMnbHMjolc= +cloud.google.com/go/iam v1.5.3/go.mod h1:MR3v9oLkZCTlaqljW6Eb2d3HGDGK5/bDv93jhfISFvU= +cloud.google.com/go/logging v1.13.0 h1:7j0HgAp0B94o1YRDqiqm26w4q1rDMH7XNRU34lJXHYc= +cloud.google.com/go/logging v1.13.0/go.mod h1:36CoKh6KA/M0PbhPKMq6/qety2DCAErbhXT62TuXALA= +cloud.google.com/go/longrunning v0.7.0 h1:FV0+SYF1RIj59gyoWDRi45GiYUMM3K1qO51qoboQT1E= +cloud.google.com/go/longrunning v0.7.0/go.mod h1:ySn2yXmjbK9Ba0zsQqunhDkYi0+9rlXIwnoAf+h+TPY= +cloud.google.com/go/monitoring v1.24.2 h1:5OTsoJ1dXYIiMiuL+sYscLc9BumrL3CarVLL7dd7lHM= +cloud.google.com/go/monitoring v1.24.2/go.mod h1:x7yzPWcgDRnPEv3sI+jJGBkwl5qINf+6qY4eq0I9B4U= +cloud.google.com/go/storage v1.58.0 h1:PflFXlmFJjG/nBeR9B7pKddLQWaFaRWx4uUi/LyNxxo= +cloud.google.com/go/storage v1.58.0/go.mod h1:cMWbtM+anpC74gn6qjLh+exqYcfmB9Hqe5z6adx+CLI= +cloud.google.com/go/trace v1.11.6 h1:2O2zjPzqPYAHrn3OKl029qlqG6W8ZdYaOWRyr8NgMT4= +cloud.google.com/go/trace v1.11.6/go.mod h1:GA855OeDEBiBMzcckLPE2kDunIpC72N+Pq8WFieFjnI= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.29.0 h1:UQUsRi8WTzhZntp5313l+CHIAT95ojUI2lpP/ExlZa4= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.29.0/go.mod h1:Cz6ft6Dkn3Et6l2v2a9/RpN7epQ1GtDlO6lj8bEcOvw= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.54.0 h1:lhhYARPUu3LmHysQ/igznQphfzynnqI3D75oUyw1HXk= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.54.0/go.mod h1:l9rva3ApbBpEJxSNYnwT9N4CDLrWgtq3u8736C5hyJw= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.54.0 h1:xfK3bbi6F2RDtaZFtUdKO3osOBIhNb+xTs8lFW6yx9o= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.54.0/go.mod h1:vB2GH9GAYYJTO3mEn8oYwzEdhlayZIdQz6zdzgUIRvA= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.54.0 h1:s0WlVbf9qpvkh1c/uDAPElam0WrL7fHRIidgZJ7UqZI= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.54.0/go.mod h1:Mf6O40IAyB9zR/1J8nGDDPirZQQPbYJni8Yisy7NTMc= +github.com/Ladicle/tabwriter v1.0.0 h1:DZQqPvMumBDwVNElso13afjYLNp0Z7pHqHnu0r4t9Dg= +github.com/Ladicle/tabwriter v1.0.0/go.mod h1:c4MdCjxQyTbGuQO/gvqJ+IA/89UEwrsD6hUCW98dyp4= +github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0= +github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= +github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= +github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= +github.com/alecthomas/chroma/v2 v2.23.1 h1:nv2AVZdTyClGbVQkIzlDm/rnhk1E9bU9nXwmZ/Vk/iY= +github.com/alecthomas/chroma/v2 v2.23.1/go.mod h1:NqVhfBR0lte5Ouh3DcthuUCTUpDC9cxBOfyMbMQPs3o= +github.com/alecthomas/repr v0.5.2 h1:SU73FTI9D1P5UNtvseffFSGmdNci/O6RsqzeXJtP0Qs= +github.com/alecthomas/repr v0.5.2/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= +github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= +github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= +github.com/aws/aws-sdk-go-v2 v1.41.0 h1:tNvqh1s+v0vFYdA1xq0aOJH+Y5cRyZ5upu6roPgPKd4= +github.com/aws/aws-sdk-go-v2 v1.41.0/go.mod h1:MayyLB8y+buD9hZqkCW3kX1AKq07Y5pXxtgB+rRFhz0= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.4 h1:489krEF9xIGkOaaX3CE/Be2uWjiXrkCH6gUX+bZA/BU= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.4/go.mod h1:IOAPF6oT9KCsceNTvvYMNHy0+kMF8akOjeDvPENWxp4= +github.com/aws/aws-sdk-go-v2/config v1.32.6 h1:hFLBGUKjmLAekvi1evLi5hVvFQtSo3GYwi+Bx4lpJf8= +github.com/aws/aws-sdk-go-v2/config v1.32.6/go.mod h1:lcUL/gcd8WyjCrMnxez5OXkO3/rwcNmvfno62tnXNcI= +github.com/aws/aws-sdk-go-v2/credentials v1.19.6 h1:F9vWao2TwjV2MyiyVS+duza0NIRtAslgLUM0vTA1ZaE= +github.com/aws/aws-sdk-go-v2/credentials v1.19.6/go.mod h1:SgHzKjEVsdQr6Opor0ihgWtkWdfRAIwxYzSJ8O85VHY= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.16 h1:80+uETIWS1BqjnN9uJ0dBUaETh+P1XwFy5vwHwK5r9k= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.16/go.mod h1:wOOsYuxYuB/7FlnVtzeBYRcjSRtQpAW0hCP7tIULMwo= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.16 h1:rgGwPzb82iBYSvHMHXc8h9mRoOUBZIGFgKb9qniaZZc= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.16/go.mod h1:L/UxsGeKpGoIj6DxfhOWHWQ/kGKcd4I1VncE4++IyKA= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.16 h1:1jtGzuV7c82xnqOVfx2F0xmJcOw5374L7N6juGW6x6U= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.16/go.mod h1:M2E5OQf+XLe+SZGmmpaI2yy+J326aFf6/+54PoxSANc= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 h1:WKuaxf++XKWlHWu9ECbMlha8WOEGm0OUEZqm4K/Gcfk= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4/go.mod h1:ZWy7j6v1vWGmPReu0iSGvRiise4YI5SkR3OHKTZ6Wuc= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.16 h1:CjMzUs78RDDv4ROu3JnJn/Ig1r6ZD7/T2DXLLRpejic= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.16/go.mod h1:uVW4OLBqbJXSHJYA9svT9BluSvvwbzLQ2Crf6UPzR3c= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4 h1:0ryTNEdJbzUCEWkVXEXoqlXV72J5keC1GvILMOuD00E= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4/go.mod h1:HQ4qwNZh32C3CBeO6iJLQlgtMzqeG17ziAA/3KDJFow= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.7 h1:DIBqIrJ7hv+e4CmIk2z3pyKT+3B6qVMgRsawHiR3qso= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.7/go.mod h1:vLm00xmBke75UmpNvOcZQ/Q30ZFjbczeLFqGx5urmGo= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.16 h1:oHjJHeUy0ImIV0bsrX0X91GkV5nJAyv1l1CC9lnO0TI= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.16/go.mod h1:iRSNGgOYmiYwSCXxXaKb9HfOEj40+oTKn8pTxMlYkRM= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.16 h1:NSbvS17MlI2lurYgXnCOLvCFX38sBW4eiVER7+kkgsU= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.16/go.mod h1:SwT8Tmqd4sA6G1qaGdzWCJN99bUmPGHfRwwq3G5Qb+A= +github.com/aws/aws-sdk-go-v2/service/s3 v1.95.0 h1:MIWra+MSq53CFaXXAywB2qg9YvVZifkk6vEGl/1Qor0= +github.com/aws/aws-sdk-go-v2/service/s3 v1.95.0/go.mod h1:79S2BdqCJpScXZA2y+cpZuocWsjGjJINyXnOsf5DTz8= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.4 h1:HpI7aMmJ+mm1wkSHIA2t5EaFFv5EFYXePW30p1EIrbQ= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.4/go.mod h1:C5RdGMYGlfM0gYq/tifqgn4EbyX99V15P2V3R+VHbQU= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.8 h1:aM/Q24rIlS3bRAhTyFurowU8A0SMyGDtEOY/l/s/1Uw= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.8/go.mod h1:+fWt2UHSb4kS7Pu8y+BMBvJF0EWx+4H0hzNwtDNRTrg= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.12 h1:AHDr0DaHIAo8c9t1emrzAlVDFp+iMMKnPdYy6XO4MCE= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.12/go.mod h1:GQ73XawFFiWxyWXMHWfhiomvP3tXtdNar/fi8z18sx0= +github.com/aws/aws-sdk-go-v2/service/sts v1.41.5 h1:SciGFVNZ4mHdm7gpD1dgZYnCuVdX1s+lFTg4+4DOy70= +github.com/aws/aws-sdk-go-v2/service/sts v1.41.5/go.mod h1:iW40X4QBmUxdP+fZNOpfmkdMZqsovezbAeO+Ubiv2pk= +github.com/aws/smithy-go v1.24.0 h1:LpilSUItNPFr1eY85RYgTIg5eIEPtvFbskaFcmmIUnk= +github.com/aws/smithy-go v1.24.0/go.mod h1:LEj2LM3rBRQJxPZTB4KuzZkaZYnZPnvgIhb4pu07mx0= +github.com/aymanbagabas/go-udiff v0.4.0 h1:TKnLPh7IbnizJIBKFWa9mKayRUBQ9Kh1BPCk6w2PnYM= +github.com/aymanbagabas/go-udiff v0.4.0/go.mod h1:0L9PGwj20lrtmEMeyw4WKJ/TMyDtvAoK9bf2u/mNo3w= +github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas= +github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chainguard-dev/git-urls v1.0.2 h1:pSpT7ifrpc5X55n4aTTm7FFUE+ZQHKiqpiwNkJrVcKQ= +github.com/chainguard-dev/git-urls v1.0.2/go.mod h1:rbGgj10OS7UgZlbzdUQIQpT0k/D4+An04HJY7Ol+Y/o= +github.com/charmbracelet/colorprofile v0.4.2 h1:BdSNuMjRbotnxHSfxy+PCSa4xAmz7szw70ktAtWRYrY= +github.com/charmbracelet/colorprofile v0.4.2/go.mod h1:0rTi81QpwDElInthtrQ6Ni7cG0sDtwAd4C4le060fT8= +github.com/charmbracelet/ultraviolet v0.0.0-20260205113103-524a6607adb8 h1:eyFRbAmexyt43hVfeyBofiGSEmJ7krjLOYt/9CF5NKA= +github.com/charmbracelet/ultraviolet v0.0.0-20260205113103-524a6607adb8/go.mod h1:SQpCTRNBtzJkwku5ye4S3HEuthAlGy2n9VXZnWkEW98= +github.com/charmbracelet/x/ansi v0.11.6 h1:GhV21SiDz/45W9AnV2R61xZMRri5NlLnl6CVF7ihZW8= +github.com/charmbracelet/x/ansi v0.11.6/go.mod h1:2JNYLgQUsyqaiLovhU2Rv/pb8r6ydXKS3NIttu3VGZQ= +github.com/charmbracelet/x/exp/golden v0.0.0-20250806222409-83e3a29d542f h1:pk6gmGpCE7F3FcjaOEKYriCvpmIN4+6OS/RD0vm4uIA= +github.com/charmbracelet/x/exp/golden v0.0.0-20250806222409-83e3a29d542f/go.mod h1:IfZAMTHB6XkZSeXUqriemErjAWCCzT0LwjKFYCZyw0I= +github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSgfgZRk= +github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI= +github.com/charmbracelet/x/termios v0.1.1 h1:o3Q2bT8eqzGnGPOYheoYS8eEleT5ZVNYNy8JawjaNZY= +github.com/charmbracelet/x/termios v0.1.1/go.mod h1:rB7fnv1TgOPOyyKRJ9o+AsTU/vK5WHJ2ivHeut/Pcwo= +github.com/charmbracelet/x/windows v0.2.2 h1:IofanmuvaxnKHuV04sC0eBy/smG6kIKrWG2/jYn2GuM= +github.com/charmbracelet/x/windows v0.2.2/go.mod h1:/8XtdKZzedat74NQFn0NGlGL4soHB0YQZrETF96h75k= +github.com/clipperhouse/displaywidth v0.11.0 h1:lBc6kY44VFw+TDx4I8opi/EtL9m20WSEFgwIwO+UVM8= +github.com/clipperhouse/displaywidth v0.11.0/go.mod h1:bkrFNkf81G8HyVqmKGxsPufD3JhNl3dSqnGhOoSD/o0= +github.com/clipperhouse/uax29/v2 v2.7.0 h1:+gs4oBZ2gPfVrKPthwbMzWZDaAFPGYK72F0NJv2v7Vk= +github.com/clipperhouse/uax29/v2 v2.7.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM= +github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443 h1:aQ3y1lwWyqYPiWZThqv1aFbZMiM9vblcSArJRf2Irls= +github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= +github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s= +github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ= +github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/dominikbraun/graph v0.23.0 h1:TdZB4pPqCLFxYhdyMFb1TBdFxp8XLcJfTTBQucVPgCo= +github.com/dominikbraun/graph v0.23.0/go.mod h1:yOjYyogZLY1LSG9E33JWZJiq5k83Qy2C6POAuiViluc= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/elliotchance/orderedmap/v3 v3.1.0 h1:j4DJ5ObEmMBt/lcwIecKcoRxIQUEnw0L804lXYDt/pg= +github.com/elliotchance/orderedmap/v3 v3.1.0/go.mod h1:G+Hc2RwaZvJMcS4JpGCOyViCnGeKf0bTYCGTO4uhjSo= +github.com/envoyproxy/go-control-plane v0.13.4 h1:zEqyPVyku6IvWCFwux4x9RxkLOMUL+1vC9xUFv5l2/M= +github.com/envoyproxy/go-control-plane v0.13.4/go.mod h1:kDfuBlDVsSj2MjrLEtRWtHlsWIFcGyB2RMO44Dc5GZA= +github.com/envoyproxy/go-control-plane/envoy v1.32.4 h1:jb83lalDRZSpPWW2Z7Mck/8kXZ5CQAFYVjQcdVIr83A= +github.com/envoyproxy/go-control-plane/envoy v1.32.4/go.mod h1:Gzjc5k8JcJswLjAx1Zm+wSYE20UrLtt7JZMWiWQXQEw= +github.com/envoyproxy/go-control-plane/ratelimit v0.1.0 h1:/G9QYbddjL25KvtKTv3an9lx6VBE2cnb8wp1vEGNYGI= +github.com/envoyproxy/go-control-plane/ratelimit v0.1.0/go.mod h1:Wk+tMFAFbCXaJPzVVHnPgRKdUdwW/KdbRt94AzgRee4= +github.com/envoyproxy/protoc-gen-validate v1.2.1 h1:DEo3O99U8j4hBFwbJfrz9VtgcDfUKS7KJ7spH3d86P8= +github.com/envoyproxy/protoc-gen-validate v1.2.1/go.mod h1:d/C80l/jxXLdfEIhX1W2TmLfsJ31lvEjwamM4DxlWXU= +github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= +github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= +github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/go-jose/go-jose/v4 v4.1.2 h1:TK/7NqRQZfgAh+Td8AlsrvtPoUyiHh0LqVvokh+1vHI= +github.com/go-jose/go-jose/v4 v4.1.2/go.mod h1:22cg9HWM1pOlnRiY+9cQYJ9XHmya1bYW8OeDM6Ku6Oo= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI= +github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow= +github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= +github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= +github.com/go-task/task/v3 v3.49.1 h1:OR9WXLzliHXfrXl21sGLk4l45Rk6hGDJ1W7MhkioG+Y= +github.com/go-task/task/v3 v3.49.1/go.mod h1:5E84IeThhWRK9ksT1D7jQNtu+bvmYVkfJVlXHz3bD0A= +github.com/go-task/template v0.2.0 h1:xW7ek0o65FUSTbKcSNeg2Vyf/I7wYXFgLUznptvviBE= +github.com/go-task/template v0.2.0/go.mod h1:dbdoUb6qKnHQi1y6o+IdIrs0J4o/SEhSTA6bbzZmdtc= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/martian/v3 v3.3.3 h1:DIhPTQrbPkgs2yJYdXU/eNACCG5DVQjySNRNlflZ9Fc= +github.com/google/martian/v3 v3.3.3/go.mod h1:iEPrYcgCF7jA9OtScMFQyAlZZ4YXTKEtJ1E6RWzmBA0= +github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0= +github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.3.7 h1:zrn2Ee/nWmHulBx5sAVrGgAa0f2/R35S4DJwfFaUPFQ= +github.com/googleapis/enterprise-certificate-proxy v0.3.7/go.mod h1:MkHOF77EYAE7qfSuSS9PU6g4Nt4e11cnsDUowfwewLA= +github.com/googleapis/gax-go/v2 v2.15.0 h1:SyjDc1mGgZU5LncH8gimWo9lW1DtIfPibOG81vgd/bo= +github.com/googleapis/gax-go/v2 v2.15.0/go.mod h1:zVVkkxAQHa1RQpg9z2AUCMnKhi0Qld9rcmyfL1OZhoc= +github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.70 h1:0HADrxxqaQkGycO1JoUUA+B4FnIkuo8d2bz/hSaTFFQ= +github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.70/go.mod h1:fm2FdDCzJdtbXF7WKAMvBb5NEPouXPHFbGNYs9ShFns= +github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-getter v1.8.4 h1:hGEd2xsuVKgwkMtPVufq73fAmZU/x65PPcqH3cb0D9A= +github.com/hashicorp/go-getter v1.8.4/go.mod h1:x27pPGSg9kzoB147QXI8d/nDvp2IgYGcwuRjpaXE9Yg= +github.com/hashicorp/go-version v1.8.0 h1:KAkNb1HAiZd1ukkxDFGmokVZe1Xy9HG6NUp+bPle2i4= +github.com/hashicorp/go-version v1.8.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= +github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= +github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= +github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/klauspost/compress v1.18.2 h1:iiPHWW0YrcFgpBYhsA6D1+fqHssJscY/Tm/y2Uqnapk= +github.com/klauspost/compress v1.18.2/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4= +github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE= +github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= +github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU= +github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lucasb-eyer/go-colorful v1.3.0 h1:2/yBRLdWBZKrf7gB40FoiKfAWYQ0lqNcbuQwVHXptag= +github.com/lucasb-eyer/go-colorful v1.3.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= +github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= +github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.20 h1:WcT52H91ZUAwy8+HUkdM3THM6gXqXuLJi9O3rjcQQaQ= +github.com/mattn/go-runewidth v0.0.20/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4= +github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE= +github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= +github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= +github.com/pierrec/lz4/v4 v4.1.22 h1:cKFw6uJDK+/gfw5BcDL0JL5aBsAFdsIT18eRtLj7VIU= +github.com/pierrec/lz4/v4 v4.1.22/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/puzpuzpuz/xsync/v4 v4.4.0 h1:vlSN6/CkEY0pY8KaB0yqo/pCLZvp9nhdbBdjipT4gWo= +github.com/puzpuzpuz/xsync/v4 v4.4.0/go.mod h1:VJDmTCJMBt8igNxnkQd86r+8KUeN1quSfNKu5bLYFQo= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +github.com/sajari/fuzzy v1.0.0 h1:+FmwVvJErsd0d0hAPlj4CxqxUtQY/fOoY0DwX4ykpRY= +github.com/sajari/fuzzy v1.0.0/go.mod h1:OjYR6KxoWOe9+dOlXeiCJd4dIbED4Oo8wpS89o0pwOo= +github.com/sebdah/goldie/v2 v2.8.0 h1:dZb9wR8q5++oplmEiJT+U/5KyotVD+HNGCAc5gNr8rc= +github.com/sebdah/goldie/v2 v2.8.0/go.mod h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvKI/NNtssI= +github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= +github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= +github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= +github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spiffe/go-spiffe/v2 v2.5.0 h1:N2I01KCUkv1FAjZXJMwh95KK1ZIQLYbPfhaxw8WS0hE= +github.com/spiffe/go-spiffe/v2 v2.5.0/go.mod h1:P+NxobPc6wXhVtINNtFjNWGBTreew1GBUCwT2wPmb7g= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/u-root/u-root v0.15.1-0.20251208185023-2f8c7e763cf8 h1:cq+DjLAjz3ZPwh0+G571O/jMH0c0DzReDPLjQGL2/BA= +github.com/u-root/u-root v0.15.1-0.20251208185023-2f8c7e763cf8/go.mod h1:JNauIV2zopCBv/6o+umxcT3bKe8YUqYJaTZQYSYpKss= +github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701 h1:pyC9PaHYZFgEKFdlp3G8RaCKgVpHZnecvArXvPXcFkM= +github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701/go.mod h1:P3a5rG4X7tI17Nn3aOIAYr5HbIMukwXG0urG0WuL8OA= +github.com/ulikunitz/xz v0.5.15 h1:9DNdB5s+SgV3bQ2ApL10xRc35ck0DuIX/isZvIk+ubY= +github.com/ulikunitz/xz v0.5.15/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= +github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= +github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ= +github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= +github.com/zeebo/errs v1.4.0 h1:XNdoD/RRMKP7HD0UhJnIzUy74ISdGGxURlYG8HSWSfM= +github.com/zeebo/errs v1.4.0/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4= +github.com/zeebo/xxh3 v1.1.0 h1:s7DLGDK45Dyfg7++yxI0khrfwq9661w9EN78eP/UZVs= +github.com/zeebo/xxh3 v1.1.0/go.mod h1:IisAie1LELR4xhVinxWS5+zf1lA4p0MW4T+w+W07F5s= +go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= +go.opentelemetry.io/contrib/detectors/gcp v1.36.0 h1:F7q2tNlCaHY9nMKHR6XH9/qkp8FktLnIcy6jJNyOCQw= +go.opentelemetry.io/contrib/detectors/gcp v1.36.0/go.mod h1:IbBN8uAIIx734PTonTPxAxnjc2pQTxWNkwfstZ+6H2k= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0 h1:YH4g8lQroajqUwWbq/tr2QX1JFmEXaDLgG+ew9bLMWo= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0/go.mod h1:fvPi2qXDqFs8M4B4fmJhE92TyQs9Ydjlg3RvfUp+NbQ= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= +go.opentelemetry.io/otel v1.40.0 h1:oA5YeOcpRTXq6NN7frwmwFR0Cn3RhTVZvXsP4duvCms= +go.opentelemetry.io/otel v1.40.0/go.mod h1:IMb+uXZUKkMXdPddhwAHm6UfOwJyh4ct1ybIlV14J0g= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.38.0 h1:wm/Q0GAAykXv83wzcKzGGqAnnfLFyFe7RslekZuv+VI= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.38.0/go.mod h1:ra3Pa40+oKjvYh+ZD3EdxFZZB0xdMfuileHAm4nNN7w= +go.opentelemetry.io/otel/metric v1.40.0 h1:rcZe317KPftE2rstWIBitCdVp89A2HqjkxR3c11+p9g= +go.opentelemetry.io/otel/metric v1.40.0/go.mod h1:ib/crwQH7N3r5kfiBZQbwrTge743UDc7DTFVZrrXnqc= +go.opentelemetry.io/otel/sdk v1.40.0 h1:KHW/jUzgo6wsPh9At46+h4upjtccTmuZCFAc9OJ71f8= +go.opentelemetry.io/otel/sdk v1.40.0/go.mod h1:Ph7EFdYvxq72Y8Li9q8KebuYUr2KoeyHx0DRMKrYBUE= +go.opentelemetry.io/otel/sdk/metric v1.40.0 h1:mtmdVqgQkeRxHgRv4qhyJduP3fYJRMX4AtAlbuWdCYw= +go.opentelemetry.io/otel/sdk/metric v1.40.0/go.mod h1:4Z2bGMf0KSK3uRjlczMOeMhKU2rhUqdWNoKcYrtcBPg= +go.opentelemetry.io/otel/trace v1.40.0 h1:WA4etStDttCSYuhwvEa8OP8I5EWu24lkOzp+ZYblVjw= +go.opentelemetry.io/otel/trace v1.40.0/go.mod h1:zeAhriXecNGP/s2SEG3+Y8X9ujcJOTqQ5RgdEJcawiA= +go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= +golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU= +golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0= +golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw= +golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM= +golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU= +golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY= +golang.org/x/oauth2 v0.33.0 h1:4Q+qn+E5z8gPRJfmRy7C2gGG3T4jIprK6aSYgTXGRpo= +golang.org/x/oauth2 v0.33.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= +golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= +golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= +golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/term v0.40.0 h1:36e4zGLqU4yhjlmxEaagx2KuYbJq3EwY8K943ZsHcvg= +golang.org/x/term v0.40.0/go.mod h1:w2P8uVp06p2iyKKuvXIm7N/y0UCRt3UfJTfZ7oOpglM= +golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU= +golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY= +golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI= +golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= +gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= +gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= +google.golang.org/api v0.256.0 h1:u6Khm8+F9sxbCTYNoBHg6/Hwv0N/i+V94MvkOSor6oI= +google.golang.org/api v0.256.0/go.mod h1:KIgPhksXADEKJlnEoRa9qAII4rXcy40vfI8HRqcU964= +google.golang.org/genproto v0.0.0-20250922171735-9219d122eba9 h1:LvZVVaPE0JSqL+ZWb6ErZfnEOKIqqFWUJE2D0fObSmc= +google.golang.org/genproto v0.0.0-20250922171735-9219d122eba9/go.mod h1:QFOrLhdAe2PsTp3vQY4quuLKTi9j3XG3r6JPPaw7MSc= +google.golang.org/genproto/googleapis/api v0.0.0-20251111163417-95abcf5c77ba h1:B14OtaXuMaCQsl2deSvNkyPKIzq3BjfxQp8d00QyWx4= +google.golang.org/genproto/googleapis/api v0.0.0-20251111163417-95abcf5c77ba/go.mod h1:G5IanEx8/PgI9w6CFcYQf7jMtHQhZruvfM1i3qOqk5U= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251111163417-95abcf5c77ba h1:UKgtfRM7Yh93Sya0Fo8ZzhDP4qBckrrxEr2oF5UIVb8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251111163417-95abcf5c77ba/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= +google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A= +google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c= +google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= +google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +mvdan.cc/sh/moreinterp v0.0.0-20260120230322-19def062a997 h1:3bbJwtPFh98dJ6lxRdR3eLHTH1CmR3BcU6TriIMiXjE= +mvdan.cc/sh/moreinterp v0.0.0-20260120230322-19def062a997/go.mod h1:Qy/zdaMDxq9sT72Gi43K3gsV+TtTohyDO3f1cyBVwuo= +mvdan.cc/sh/v3 v3.12.1-0.20260124232039-e74afc18e65b h1:PUPnLxbDzRO9kg/03l7TZk7+ywTv7FxmOhDHOtOdOtk= +mvdan.cc/sh/v3 v3.12.1-0.20260124232039-e74afc18e65b/go.mod h1:mencVHx2sy9XZG5wJbCA9nRUOE3zvMtoRXOmXMxH7sc= From 6f270574a31422bd0d8a252ad284da58509eb915 Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Sun, 19 Apr 2026 19:11:22 +0200 Subject: [PATCH 03/45] ci: invoke task directly instead of make Replace `make ` with `go tool -modfile=tools/task/go.mod task ` in CI workflows and the setup-build-environment action. This skips the Makefile wrapper and surfaces task's real target names (e.g. task:exp-aitools, fmt:full) in CI logs. release-build.yml inlines the python wheel build steps (which used to live in python/Makefile) so the release job does not depend on task. Co-authored-by: Isaac --- .../setup-build-environment/action.yml | 2 +- .github/workflows/check.yml | 9 ++-- .github/workflows/push.yml | 42 ++++++++++--------- .github/workflows/python_push.yml | 24 ++++++++--- .github/workflows/release-build.yml | 4 +- 5 files changed, 49 insertions(+), 32 deletions(-) diff --git a/.github/actions/setup-build-environment/action.yml b/.github/actions/setup-build-environment/action.yml index 62d9bd66f1..58ff10d8b3 100644 --- a/.github/actions/setup-build-environment/action.yml +++ b/.github/actions/setup-build-environment/action.yml @@ -38,7 +38,7 @@ runs: version: "0.8.9" - name: Install Python versions for tests - run: make install-pythons + run: go tool -modfile=tools/task/go.mod task install-pythons shell: bash - name: Install ruff (Python linter and formatter) diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 5787f519d5..7bbbae4dc7 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -44,14 +44,13 @@ jobs: version: "0.9.1" args: "format --check" - - name: "make fmtfull: Python and Go formatting" + - name: "task fmt:full: Python and Go formatting" # Python formatting is already checked above, but this also checks Go and YAML formatting - # and verifies that the make command works correctly run: | - make fmtfull + go tool -modfile=tools/task/go.mod task fmt:full git diff --exit-code - - name: "make checks: custom checks outside of fmt and lint" + - name: "task checks: custom checks outside of fmt and lint" run: |- - make checks + go tool -modfile=tools/task/go.mod task checks git diff --exit-code diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index fcd6930f64..0246a3f97c 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -77,7 +77,7 @@ jobs: # Only run if the target is in the list of targets from testmask if: ${{ contains(fromJSON(needs.testmask.outputs.targets), 'test') }} - name: "make test (${{matrix.os.name}}, ${{matrix.deployment}})" + name: "task test (${{matrix.os.name}}, ${{matrix.deployment}})" runs-on: ${{ matrix.os.runner }} permissions: @@ -137,23 +137,23 @@ jobs: if: ${{ github.event_name == 'pull_request' || github.event_name == 'merge_group' || github.event_name == 'schedule' }} env: ENVFILTER: DATABRICKS_BUNDLE_ENGINE=${{ matrix.deployment }} - run: make test + run: go tool -modfile=tools/task/go.mod task test - name: Run tests with coverage - # Only run 'make cover' on push to main to make sure it does not get broken. + # Only run 'task cover' on push to main to make sure it does not get broken. if: ${{ github.event_name == 'push' }} env: ENVFILTER: DATABRICKS_BUNDLE_ENGINE=${{ matrix.deployment }} - run: make cover + run: go tool -modfile=tools/task/go.mod task cover - name: Analyze slow tests - run: make slowest + run: go tool -modfile=tools/task/go.mod task slowest - name: Check out.test.toml files are up to date shell: bash run: | if ! git diff --exit-code; then - echo "ERROR: detected changed files in the repository; Most likely you have out.test.toml files that are out of date. Run 'make generate-out-test-toml' to update." + echo "ERROR: detected changed files in the repository; Most likely you have out.test.toml files that are out of date. Run 'go tool -modfile=tools/task/go.mod task generate:out-test-toml' to update." exit 1 fi @@ -164,7 +164,7 @@ jobs: # Only run if the target is in the list of targets from testmask if: ${{ contains(fromJSON(needs.testmask.outputs.targets), 'test-exp-aitools') }} - name: "make test-exp-aitools (${{matrix.os.name}})" + name: "task test:exp-aitools (${{matrix.os.name}})" runs-on: ${{ matrix.os.runner }} permissions: @@ -201,7 +201,7 @@ jobs: - name: Run tests run: | - make test-exp-aitools + go tool -modfile=tools/task/go.mod task test:exp-aitools test-exp-ssh: needs: @@ -210,7 +210,7 @@ jobs: # Only run if the target is in the list of targets from testmask if: ${{ contains(fromJSON(needs.testmask.outputs.targets), 'test-exp-ssh') }} - name: "make test-exp-ssh (${{matrix.os.name}})" + name: "task test:exp-ssh (${{matrix.os.name}})" runs-on: ${{ matrix.os.runner }} permissions: @@ -246,7 +246,7 @@ jobs: - name: Run tests run: | - make test-exp-ssh + go tool -modfile=tools/task/go.mod task test:exp-ssh test-pipelines: needs: @@ -255,7 +255,7 @@ jobs: # Only run if the target is in the list of targets from testmask if: ${{ contains(fromJSON(needs.testmask.outputs.targets), 'test-pipelines') }} - name: "make test-pipelines (${{matrix.os.name}})" + name: "task test:pipelines (${{matrix.os.name}})" runs-on: ${{ matrix.os.runner }} permissions: @@ -291,7 +291,7 @@ jobs: - name: Run tests run: | - make test-pipelines + go tool -modfile=tools/task/go.mod task test:pipelines # This job groups the result of all the above test jobs. # It is a required check, so it blocks auto-merge and the merge queue. @@ -340,15 +340,15 @@ jobs: - name: Verify that the schema is up to date run: | - if ! ( make schema && git diff --exit-code ); then - echo "The schema is not up to date. Please run 'make schema' and commit the changes." + if ! ( go tool -modfile=tools/task/go.mod task --force schema && git diff --exit-code ); then + echo "The schema is not up to date. Please run 'task schema' and commit the changes." exit 1 fi - name: Verify that the generated enum and required fields are up to date run: | - if ! ( make generate-validation && git diff --exit-code ); then - echo "The generated enum and required fields are not up to date. Please run 'make generate-validation' and commit the changes." + if ! ( go tool -modfile=tools/task/go.mod task --force generate:validation && git diff --exit-code ); then + echo "The generated enum and required fields are not up to date. Please run 'task generate:validation' and commit the changes." exit 1 fi @@ -360,18 +360,22 @@ jobs: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - name: Setup Go + uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 + with: + go-version-file: go.mod + - name: Install uv uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8.0.0 with: version: "0.6.5" - name: Verify that python/codegen is up to date - working-directory: python run: |- - make codegen + go tool -modfile=tools/task/go.mod task python:codegen if ! ( git diff --exit-code ); then - echo "Generated Python code is not up-to-date. Please run 'pushd python && make codegen' and commit the changes." + echo "Generated Python code is not up-to-date. Please run 'task python:codegen' and commit the changes." exit 1 fi diff --git a/.github/workflows/python_push.yml b/.github/workflows/python_push.yml index 8a6d351dcb..7be10eaf6d 100644 --- a/.github/workflows/python_push.yml +++ b/.github/workflows/python_push.yml @@ -32,6 +32,11 @@ jobs: - name: Checkout repository and submodules uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - name: Setup Go + uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 + with: + go-version-file: go.mod + - name: Install uv uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8.0.0 with: @@ -39,8 +44,7 @@ jobs: version: "0.6.5" - name: Run tests - working-directory: python - run: make test + run: go tool -modfile=tools/task/go.mod task python:test python_linters: name: lint @@ -50,14 +54,18 @@ jobs: - name: Checkout repository and submodules uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - name: Setup Go + uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 + with: + go-version-file: go.mod + - name: Install uv uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8.0.0 with: version: "0.6.5" - name: Run lint - working-directory: python - run: make lint + run: go tool -modfile=tools/task/go.mod task python:lint python_docs: name: docs @@ -67,11 +75,15 @@ jobs: - name: Checkout repository and submodules uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - name: Setup Go + uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 + with: + go-version-file: go.mod + - name: Install uv uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8.0.0 with: version: "0.6.5" - name: Run docs - working-directory: python - run: make docs + run: go tool -modfile=tools/task/go.mod task python:docs diff --git a/.github/workflows/release-build.yml b/.github/workflows/release-build.yml index e88986e223..864e6a1e94 100644 --- a/.github/workflows/release-build.yml +++ b/.github/workflows/release-build.yml @@ -172,7 +172,9 @@ jobs: - name: Build wheel working-directory: python - run: make build + run: | + rm -rf build dist + uv build . - name: Upload Python wheel uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 From 5dc976e1f27e151e42236948e350d58a125ad0ae Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Sun, 19 Apr 2026 19:11:27 +0200 Subject: [PATCH 04/45] docs: update AGENTS.md command references for task Replace make commands with their task equivalents in the build/test and code-quality sections so AI agents and human readers see the current invocation style. Co-authored-by: Isaac --- AGENTS.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 7386b4ec50..1f90ac4104 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -12,25 +12,25 @@ When moving code from one place to another, please don't unnecessarily change th ### Building and Testing -- `make build` - Build the CLI binary -- `make test` - Run unit tests for all packages +- `task build` - Build the CLI binary +- `task test` - Run unit and acceptance tests for all packages - `go test ./acceptance -run TestAccept/bundle/// -tail -test.v` - run a single acceptance test -- `make integration` - Run integration tests (requires environment variables) -- `make cover` - Generate test coverage reports +- `task integration` - Run integration tests (requires environment variables) +- `task cover` - Generate test coverage reports ### Code Quality -- `make lint` - Run linter on changed files only (uses lintdiff.py) -- `make lintfull` - Run full linter with fixes (golangci-lint) -- `make ws` - Run whitespace linter -- `make fmt` - Format code (Go, Python, YAML) -- `make checks` - Run quick checks (tidy, whitespace, links) +- `task lint` - Run linter on changed files only (uses lintdiff.py) +- `task lint:full` - Run full linter with fixes (golangci-lint) +- `task ws` - Run whitespace linter +- `task fmt` - Format code (Go, Python, YAML) +- `task checks` - Run quick checks (tidy, whitespace, links) ### Specialized Commands -- `make schema` - Generate bundle JSON schema -- `make docs` - Generate bundle documentation -- `make generate` - Generate CLI code from OpenAPI spec (requires universe repo) +- `task schema` - Generate bundle JSON schema +- `task docs` - Generate bundle documentation +- `task generate` - Generate CLI code from OpenAPI spec (requires universe repo) ### Git Commands @@ -77,7 +77,7 @@ GIT_EDITOR=true GIT_SEQUENCE_EDITOR=true VISUAL=true GIT_PAGER=cat git rebase or # Development Tips -- Use `make test-update` to regenerate acceptance test outputs after changes +- Use `task test:update` to regenerate acceptance test outputs after changes - The CLI binary supports both `databricks` and `pipelines` command modes based on executable name - Comments should explain "why", not "what" — reviewers consistently reject comments that merely restate the code From 86202891b947104e5b637aeacd941d87276580ed Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Sun, 19 Apr 2026 19:12:30 +0200 Subject: [PATCH 05/45] Add golangci-lint configs for tools/ and tf/codegen modules MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Each submodule gets its own minimal .golangci.yaml so lint:tools and lint:codegen can run from those directories without inheriting the root config. The root config enables the ruleguard gocritic check against `libs/gorules/rule_*.go`, which golangci-lint resolves relative to the working directory — from inside tools/ or bundle/internal/tf/codegen/ that path does not exist and lint aborts before running. Co-authored-by: Isaac --- bundle/internal/tf/codegen/.golangci.yaml | 22 ++++++++++++++++++++++ tools/.golangci.yaml | 22 ++++++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 bundle/internal/tf/codegen/.golangci.yaml create mode 100644 tools/.golangci.yaml diff --git a/bundle/internal/tf/codegen/.golangci.yaml b/bundle/internal/tf/codegen/.golangci.yaml new file mode 100644 index 0000000000..49ae04f476 --- /dev/null +++ b/bundle/internal/tf/codegen/.golangci.yaml @@ -0,0 +1,22 @@ +version: "2" +linters: + default: none + enable: + - bodyclose + - errcheck + - gocritic + - govet + - ineffassign + - intrange + - mirror + - perfsprint + - revive + - staticcheck + - testifylint + - unconvert + - unused + - copyloopvar + settings: + gocritic: + disabled-checks: + - ruleguard diff --git a/tools/.golangci.yaml b/tools/.golangci.yaml new file mode 100644 index 0000000000..49ae04f476 --- /dev/null +++ b/tools/.golangci.yaml @@ -0,0 +1,22 @@ +version: "2" +linters: + default: none + enable: + - bodyclose + - errcheck + - gocritic + - govet + - ineffassign + - intrange + - mirror + - perfsprint + - revive + - staticcheck + - testifylint + - unconvert + - unused + - copyloopvar + settings: + gocritic: + disabled-checks: + - ruleguard From 9f2873a1dc36ed76805ace33ea8b80669c7588fe Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Sun, 19 Apr 2026 19:17:08 +0200 Subject: [PATCH 06/45] Add ./task wrapper script Shortens `go tool -modfile=tools/task/go.mod task ` to `./task ` and resolves the modfile via `git rev-parse --show-toplevel` so the script works from any subdirectory. Co-authored-by: Isaac --- task | 2 ++ 1 file changed, 2 insertions(+) create mode 100755 task diff --git a/task b/task new file mode 100755 index 0000000000..140f73beaf --- /dev/null +++ b/task @@ -0,0 +1,2 @@ +#!/bin/sh +exec go tool -modfile="$(git rev-parse --show-toplevel)/tools/task/go.mod" task "$@" From 008400a96bc31c35e97eae115141077a1522eaff Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Sun, 19 Apr 2026 19:23:24 +0200 Subject: [PATCH 07/45] Use ./task wrapper everywhere MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace every `go tool -modfile=tools/task/go.mod task` invocation in CI workflows, the Makefile wrapper, and the dbr:test deco command with the shorter `./task`. The dbr:test command previously pointed at tools/go.mod, which does not include task as a tool — the wrapper fixes that too. Co-authored-by: Isaac --- .../setup-build-environment/action.yml | 2 +- .github/workflows/check.yml | 4 ++-- .github/workflows/push.yml | 20 +++++++++---------- .github/workflows/python_push.yml | 6 +++--- Makefile | 3 +-- Taskfile.yml | 2 +- 6 files changed, 18 insertions(+), 19 deletions(-) diff --git a/.github/actions/setup-build-environment/action.yml b/.github/actions/setup-build-environment/action.yml index 58ff10d8b3..9f5408d57d 100644 --- a/.github/actions/setup-build-environment/action.yml +++ b/.github/actions/setup-build-environment/action.yml @@ -38,7 +38,7 @@ runs: version: "0.8.9" - name: Install Python versions for tests - run: go tool -modfile=tools/task/go.mod task install-pythons + run: ./task install-pythons shell: bash - name: Install ruff (Python linter and formatter) diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 7bbbae4dc7..d4f603e751 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -47,10 +47,10 @@ jobs: - name: "task fmt:full: Python and Go formatting" # Python formatting is already checked above, but this also checks Go and YAML formatting run: | - go tool -modfile=tools/task/go.mod task fmt:full + ./task fmt:full git diff --exit-code - name: "task checks: custom checks outside of fmt and lint" run: |- - go tool -modfile=tools/task/go.mod task checks + ./task checks git diff --exit-code diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 0246a3f97c..1ef4bc6637 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -137,23 +137,23 @@ jobs: if: ${{ github.event_name == 'pull_request' || github.event_name == 'merge_group' || github.event_name == 'schedule' }} env: ENVFILTER: DATABRICKS_BUNDLE_ENGINE=${{ matrix.deployment }} - run: go tool -modfile=tools/task/go.mod task test + run: ./task test - name: Run tests with coverage # Only run 'task cover' on push to main to make sure it does not get broken. if: ${{ github.event_name == 'push' }} env: ENVFILTER: DATABRICKS_BUNDLE_ENGINE=${{ matrix.deployment }} - run: go tool -modfile=tools/task/go.mod task cover + run: ./task cover - name: Analyze slow tests - run: go tool -modfile=tools/task/go.mod task slowest + run: ./task slowest - name: Check out.test.toml files are up to date shell: bash run: | if ! git diff --exit-code; then - echo "ERROR: detected changed files in the repository; Most likely you have out.test.toml files that are out of date. Run 'go tool -modfile=tools/task/go.mod task generate:out-test-toml' to update." + echo "ERROR: detected changed files in the repository; Most likely you have out.test.toml files that are out of date. Run './task generate:out-test-toml' to update." exit 1 fi @@ -201,7 +201,7 @@ jobs: - name: Run tests run: | - go tool -modfile=tools/task/go.mod task test:exp-aitools + ./task test:exp-aitools test-exp-ssh: needs: @@ -246,7 +246,7 @@ jobs: - name: Run tests run: | - go tool -modfile=tools/task/go.mod task test:exp-ssh + ./task test:exp-ssh test-pipelines: needs: @@ -291,7 +291,7 @@ jobs: - name: Run tests run: | - go tool -modfile=tools/task/go.mod task test:pipelines + ./task test:pipelines # This job groups the result of all the above test jobs. # It is a required check, so it blocks auto-merge and the merge queue. @@ -340,14 +340,14 @@ jobs: - name: Verify that the schema is up to date run: | - if ! ( go tool -modfile=tools/task/go.mod task --force schema && git diff --exit-code ); then + if ! ( ./task --force schema && git diff --exit-code ); then echo "The schema is not up to date. Please run 'task schema' and commit the changes." exit 1 fi - name: Verify that the generated enum and required fields are up to date run: | - if ! ( go tool -modfile=tools/task/go.mod task --force generate:validation && git diff --exit-code ); then + if ! ( ./task --force generate:validation && git diff --exit-code ); then echo "The generated enum and required fields are not up to date. Please run 'task generate:validation' and commit the changes." exit 1 fi @@ -372,7 +372,7 @@ jobs: - name: Verify that python/codegen is up to date run: |- - go tool -modfile=tools/task/go.mod task python:codegen + ./task python:codegen if ! ( git diff --exit-code ); then echo "Generated Python code is not up-to-date. Please run 'task python:codegen' and commit the changes." diff --git a/.github/workflows/python_push.yml b/.github/workflows/python_push.yml index 7be10eaf6d..b26451aec3 100644 --- a/.github/workflows/python_push.yml +++ b/.github/workflows/python_push.yml @@ -44,7 +44,7 @@ jobs: version: "0.6.5" - name: Run tests - run: go tool -modfile=tools/task/go.mod task python:test + run: ./task python:test python_linters: name: lint @@ -65,7 +65,7 @@ jobs: version: "0.6.5" - name: Run lint - run: go tool -modfile=tools/task/go.mod task python:lint + run: ./task python:lint python_docs: name: docs @@ -86,4 +86,4 @@ jobs: version: "0.6.5" - name: Run docs - run: go tool -modfile=tools/task/go.mod task python:docs + run: ./task python:docs diff --git a/Makefile b/Makefile index 66e096d090..b1ce405b07 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,3 @@ -TASK := go tool -modfile=tools/task/go.mod task .PHONY: $(MAKECMDGOALS) %: - @$(TASK) "$@" + @./task "$@" diff --git a/Taskfile.yml b/Taskfile.yml index 4d9b23986b..6299d2bae9 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -415,7 +415,7 @@ tasks: dbr:test: desc: Run DBR tests via deco env (requires deco + aws-prod-ucws access) cmds: - - "deco env run -i -n aws-prod-ucws -- go tool -modfile=tools/go.mod task dbr:integration" + - "deco env run -i -n aws-prod-ucws -- ./task dbr:integration" # --- Code generation --- From a9b1fba6339d36f088d09ad0fdbac772b32a3c39 Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Sun, 19 Apr 2026 20:16:13 +0200 Subject: [PATCH 08/45] Fix sources/generates in Taskfile and split fmt per language - build: correct generates from `databricks` to `cli` (Go module name) - drop build:vm (unused) - snapshot, snapshot:release, schema:for-docs, docs: add sources/generates - lint:tools, lint:codegen: include .golangci.yaml, go.mod, go.sum in sources - python:docs, python:codegen: include docs and databricks inputs - split fmt into fmt:python, fmt:go, fmt:yaml; fmt and fmt:full dispatch the three in parallel via deps Co-authored-by: Isaac --- Taskfile.yml | 89 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 73 insertions(+), 16 deletions(-) diff --git a/Taskfile.yml b/Taskfile.yml index 6299d2bae9..d40c64d044 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -63,6 +63,9 @@ tasks: dir: tools sources: - "**/*.go" + - .golangci.yaml + - go.mod + - go.sum cmds: - go tool -modfile={{.ROOT_DIR}}/tools/go.mod golangci-lint run ./... @@ -71,25 +74,46 @@ tasks: dir: bundle/internal/tf/codegen sources: - "**/*.go" + - .golangci.yaml + - go.mod + - go.sum cmds: - go tool -modfile={{.ROOT_DIR}}/tools/go.mod golangci-lint run ./... # --- Formatting --- - fmt: - desc: Format changed files (Python, Go, YAML; diff against main) + fmt:python: + desc: Format Python files + sources: + - "**/*.py" cmds: - ruff format -n - - ./tools/lintdiff.py go tool -modfile=tools/go.mod golangci-lint fmt - - go tool -modfile=tools/go.mod yamlfmt . - fmt:full: - desc: Format all files (Python, Go, YAML) + fmt:go: + desc: Format Go files + sources: + - "**/*.go" + - .golangci.yaml cmds: - - ruff format -n - go tool -modfile=tools/go.mod golangci-lint fmt + + fmt:yaml: + desc: Format YAML files + sources: + - "**/*.yml" + - "**/*.yaml" + - yamlfmt.yml + cmds: - go tool -modfile=tools/go.mod yamlfmt . + fmt: + desc: Format all files (Python, Go, YAML) + deps: ['fmt:python', 'fmt:go', 'fmt:yaml'] + + fmt:full: + desc: Format all files (Python, Go, YAML) + deps: ['fmt:python', 'fmt:go', 'fmt:yaml'] + # --- Code checks --- tidy: @@ -143,25 +167,30 @@ tasks: - go.mod - go.sum generates: - - databricks + - cli cmds: - go build - build:vm: - desc: Build in VM environment (no VCS stamping) - deps: [tidy] - sources: - - "**/*.go" - cmds: - - go build -buildvcs=false - snapshot: desc: Build snapshot binary to .databricks/databricks + sources: + - "**/*.go" + - go.mod + - go.sum + generates: + - .databricks/databricks cmds: - go build -o .databricks/databricks snapshot:release: desc: Build release binaries locally without uploading + sources: + - "**/*.go" + - go.mod + - go.sum + - .goreleaser.yaml + generates: + - dist/** cmds: - goreleaser release --clean --skip docker --snapshot @@ -429,11 +458,32 @@ tasks: schema:for-docs: desc: Generate bundle JSON schema for documentation + sources: + - bundle/internal/schema/*.go + - bundle/internal/schema/annotations*.yml + - bundle/config/**/*.go + - libs/jsonschema/**/*.go + - go.mod + - go.sum + generates: + - bundle/schema/jsonschema_for_docs.json cmds: - go run ./bundle/internal/schema ./bundle/internal/schema ./bundle/schema/jsonschema_for_docs.json --docs docs: desc: Generate bundle documentation + sources: + - bundle/docsgen/*.go + - bundle/docsgen/templates/** + - bundle/internal/schema/annotations*.yml + - bundle/internal/annotation/*.go + - bundle/config/**/*.go + - libs/jsonschema/**/*.go + - go.mod + - go.sum + generates: + - bundle/docsgen/output/reference.md + - bundle/docsgen/output/resources.md cmds: - go run ./bundle/docsgen ./bundle/internal/schema ./bundle/docsgen @@ -557,6 +607,9 @@ tasks: dir: python sources: - "**/*.py" + - docs/** + generates: + - docs/_output/** cmds: - uv run --python 3.12 sphinx-build docs docs/_output --show-traceback --nitpicky --fresh-env --keep-going @@ -565,6 +618,10 @@ tasks: dir: python sources: - codegen/** + - databricks/** + - databricks_tests/** + generates: + - databricks/bundles/** cmds: - | find databricks/bundles -type d -mindepth 1 -maxdepth 1 \ From a5fb2b2228281ab06d57e2dd60ff3c9965836c40 Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Sun, 19 Apr 2026 20:23:19 +0200 Subject: [PATCH 09/45] Document fmt:go module-spanning behavior Co-authored-by: Isaac --- Taskfile.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Taskfile.yml b/Taskfile.yml index d40c64d044..fa83bde834 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -91,6 +91,9 @@ tasks: fmt:go: desc: Format Go files + # `golangci-lint fmt` walks the filesystem and doesn't typecheck, so it + # formats files across all nested modules (tools/, bundle/internal/tf/codegen/) + # in a single invocation. sources: - "**/*.go" - .golangci.yaml From 4d372687346410ef4398537f7a519a348618c053 Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Sun, 19 Apr 2026 20:27:09 +0200 Subject: [PATCH 10/45] Rename lint tasks to lint:go:* and add lint:go composite Renames lint:check/lint:tools/lint:codegen to lint:go:root/lint:go:tools/ lint:go:codegen to make it explicit they're Go-specific. Adds lint:go that runs all three in parallel so a single invocation covers the whole repo. Co-authored-by: Isaac --- Taskfile.yml | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/Taskfile.yml b/Taskfile.yml index fa83bde834..7921287a69 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -50,16 +50,18 @@ tasks: cmds: - go tool -modfile=tools/go.mod golangci-lint run --fix - lint:check: - desc: Lint all Go files without fixes (root module) + # `golangci-lint run` typechecks, so it stops at go.mod boundaries. We have + # one task per Go module; `lint:go` composes them to cover the whole repo. + lint:go:root: + desc: Lint Go files in the root module (no fixes) sources: - "**/*.go" - .golangci.yaml cmds: - go tool -modfile=tools/go.mod golangci-lint run ./... - lint:tools: - desc: Lint tools/ module + lint:go:tools: + desc: Lint Go files in tools/ module dir: tools sources: - "**/*.go" @@ -69,8 +71,8 @@ tasks: cmds: - go tool -modfile={{.ROOT_DIR}}/tools/go.mod golangci-lint run ./... - lint:codegen: - desc: Lint bundle/internal/tf/codegen module + lint:go:codegen: + desc: Lint Go files in bundle/internal/tf/codegen module dir: bundle/internal/tf/codegen sources: - "**/*.go" @@ -80,6 +82,10 @@ tasks: cmds: - go tool -modfile={{.ROOT_DIR}}/tools/go.mod golangci-lint run ./... + lint:go: + desc: Lint Go files across all modules (root, tools, codegen) + deps: ['lint:go:root', 'lint:go:tools', 'lint:go:codegen'] + # --- Formatting --- fmt:python: From 761a36dbfb1b4133803459e002e577f8b9bae353 Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Sun, 19 Apr 2026 20:55:31 +0200 Subject: [PATCH 11/45] Split fmt:go into incremental (lintdiff) and full variants The `fmt` aggregate uses the incremental `fmt:go` (via lintdiff.py) for a fast interactive loop, while `fmt:full` uses `fmt:go:full` to sweep the whole tree. Python and YAML tasks are shared between the two aggregates. Co-authored-by: Isaac --- Taskfile.yml | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/Taskfile.yml b/Taskfile.yml index 7921287a69..13ae881e6d 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -96,10 +96,18 @@ tasks: - ruff format -n fmt:go: - desc: Format Go files - # `golangci-lint fmt` walks the filesystem and doesn't typecheck, so it - # formats files across all nested modules (tools/, bundle/internal/tf/codegen/) - # in a single invocation. + desc: Format changed Go files (diff vs main) + sources: + - "**/*.go" + - .golangci.yaml + cmds: + - ./tools/lintdiff.py go tool -modfile=tools/go.mod golangci-lint fmt + + # `golangci-lint fmt` walks the filesystem and doesn't typecheck, so it + # formats files across all nested modules (tools/, bundle/internal/tf/codegen/) + # in a single invocation. + fmt:go:full: + desc: Format all Go files sources: - "**/*.go" - .golangci.yaml @@ -116,12 +124,12 @@ tasks: - go tool -modfile=tools/go.mod yamlfmt . fmt: - desc: Format all files (Python, Go, YAML) + desc: Format changed files (Python, incremental Go, YAML) deps: ['fmt:python', 'fmt:go', 'fmt:yaml'] fmt:full: - desc: Format all files (Python, Go, YAML) - deps: ['fmt:python', 'fmt:go', 'fmt:yaml'] + desc: Format all files (Python, full Go, YAML) + deps: ['fmt:python', 'fmt:go:full', 'fmt:yaml'] # --- Code checks --- From ee27be6c589ac07bed231054edba6e97ce4416ad Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Sun, 19 Apr 2026 21:36:34 +0200 Subject: [PATCH 12/45] Trim build sources and delete orphaned _build-yamlfmt task MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The root CLI binary only imports from bundle/, cmd/, experimental/, internal/, libs/, so test-only trees (acceptance/, integration/), the tools/ and bundle/internal/tf/codegen/ submodules, and _test.go files are excluded from build/snapshot/snapshot:release source globs. This lets Task's checksum cache skip rebuilds when only tests change. Task v3 uses `- exclude: ` for glob exclusion (the `!` prefix from doublestar isn't honored by Task's source matching). Also remove the _build-yamlfmt task — nothing referenced it, and acceptance tests build yamlfmt directly via BuildYamlfmt with exeSuffix for Windows. Co-authored-by: Isaac --- Taskfile.yml | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/Taskfile.yml b/Taskfile.yml index 13ae881e6d..2b632feacc 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -20,18 +20,6 @@ tasks: - task: python:lint - task: python:test - # --- Tool binaries (for acceptance tests that call them by path) --- - - _build-yamlfmt: - internal: true - sources: - - tools/go.mod - - tools/go.sum - generates: - - tools/yamlfmt - cmds: - - go build -modfile=tools/go.mod -o tools/yamlfmt github.com/google/yamlfmt/cmd/yamlfmt - # --- Linting --- lint: @@ -176,11 +164,19 @@ tasks: # --- Building --- + # The root binary only imports bundle/, cmd/, experimental/, internal/, libs/, + # so changes to test-only trees (acceptance/, integration/), separate modules + # (tools/, bundle/internal/tf/codegen/), and _test.go files don't affect the build. build: desc: Build the CLI binary deps: [tidy] sources: - "**/*.go" + - exclude: "**/*_test.go" + - exclude: acceptance/** + - exclude: integration/** + - exclude: tools/** + - exclude: bundle/internal/tf/codegen/** - go.mod - go.sum generates: @@ -192,6 +188,11 @@ tasks: desc: Build snapshot binary to .databricks/databricks sources: - "**/*.go" + - exclude: "**/*_test.go" + - exclude: acceptance/** + - exclude: integration/** + - exclude: tools/** + - exclude: bundle/internal/tf/codegen/** - go.mod - go.sum generates: @@ -203,6 +204,11 @@ tasks: desc: Build release binaries locally without uploading sources: - "**/*.go" + - exclude: "**/*_test.go" + - exclude: acceptance/** + - exclude: integration/** + - exclude: tools/** + - exclude: bundle/internal/tf/codegen/** - go.mod - go.sum - .goreleaser.yaml From 23f93a0f70aa6ebb3f8e359748de343f3f488286 Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Sun, 19 Apr 2026 21:55:52 +0200 Subject: [PATCH 13/45] Refactor code generation tasks under generate:* namespace MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce `generate` as an aggregator that runs each generator in sequence: - `generate:commands` (universe + genkit; was top-level `generate`) - `generate:schema` (was `schema`; now has tight sources, no longer gated by `git diff` against merge-base) - `generate:schema-docs` (was `schema:for-docs`) - `generate:docs` (was `docs`) - `generate:validation` (now has tight sources) - `generate:direct` (unchanged) - `generate:openapi-json` (was `codegen:openapi-json`) Each reflection-based generator (schema, schema-docs, validation, docs) lists its Go sources explicitly and includes `go.mod`/`go.sum`, so the aggregator picks up SDK version bumps from `generate:commands` automatically. Test files are excluded from the source globs. Trim `tools/post-generate.sh` to only post-process genkit output (consistency check, tagging.py relocation, whitespace fix). The former `make schema`/`make schema-for-docs`/`make generate-validation`/ `make -C python codegen` calls are gone — those run as standalone tasks in the aggregator now. Update `.github/workflows/push.yml`, `AGENTS.md`, `.agent/rules/auto-generated-files.md`, `.agent/skills/pr-checklist/SKILL.md`, `bundle/docsgen/README.md`, and schema test comments to reference the new task names. Also add `.databricks/` (snapshot binary output) to `.gitignore`. Co-authored-by: Isaac --- .agent/rules/auto-generated-files.md | 18 ++-- .agent/skills/pr-checklist/SKILL.md | 4 +- .github/workflows/push.yml | 4 +- .gitignore | 3 + AGENTS.md | 7 +- Taskfile.yml | 121 ++++++++++++++++++--------- bundle/docsgen/README.md | 8 +- bundle/internal/schema/main_test.go | 4 +- tools/post-generate.sh | 23 ++--- 9 files changed, 118 insertions(+), 74 deletions(-) diff --git a/.agent/rules/auto-generated-files.md b/.agent/rules/auto-generated-files.md index 6393a64075..e2ace0def5 100644 --- a/.agent/rules/auto-generated-files.md +++ b/.agent/rules/auto-generated-files.md @@ -63,23 +63,25 @@ If a change is needed in any matched file: ### Core generation commands +- Everything, in one shot: + - `task generate` — aggregator that runs all generators below - OpenAPI SDK/CLI command stubs and related generated artifacts: - - `make generate` - - Includes generated `cmd/account/**`, `cmd/workspace/**`, `.gitattributes`, `internal/genkit/tagging.py`, and direct engine refresh. + - `task generate:commands` + - Includes generated `cmd/account/**`, `cmd/workspace/**`, `.gitattributes`, `internal/genkit/tagging.py`. - Direct engine generated YAML: - - `make generate-direct` (or `make generate-direct-apitypes`, `make generate-direct-resources`) + - `task generate:direct` (or `task generate:direct-apitypes`, `task generate:direct-resources`) - Bundle schemas: - - `make schema` - - `make schema-for-docs` + - `task generate:schema` + - `task generate:schema-docs` - This can also refresh `bundle/internal/schema/annotations_openapi.yml` when OpenAPI annotation extraction is enabled. - Bundle docs: - - `make docs` + - `task generate:docs` - Validation generated code: - - `make generate-validation` + - `task generate:validation` - Mock files: - `go run github.com/vektra/mockery/v2@b9df18e0f7b94f0bc11af3f379c8a9aea1e1e8da` - Python bundle codegen: - - `make -C python codegen` + - `task python:codegen` ### Acceptance and test generated outputs diff --git a/.agent/skills/pr-checklist/SKILL.md b/.agent/skills/pr-checklist/SKILL.md index ae21c13ca0..c672e97757 100644 --- a/.agent/skills/pr-checklist/SKILL.md +++ b/.agent/skills/pr-checklist/SKILL.md @@ -17,10 +17,10 @@ make lintfull make test # 4. If you changed bundle config structs or schema-related code: -make schema +task generate:schema # 5. If you changed files in python/: -cd python && make codegen && make test && make lint && make docs +task python:codegen python:test python:lint python:docs # 6. If you changed experimental/aitools or experimental/ssh: make test-exp-aitools # only if aitools code changed diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 1ef4bc6637..d0d237fb1f 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -340,8 +340,8 @@ jobs: - name: Verify that the schema is up to date run: | - if ! ( ./task --force schema && git diff --exit-code ); then - echo "The schema is not up to date. Please run 'task schema' and commit the changes." + if ! ( ./task --force generate:schema && git diff --exit-code ); then + echo "The schema is not up to date. Please run 'task generate:schema' and commit the changes." exit 1 fi diff --git a/.gitignore b/.gitignore index 6e0a29ed9e..9356630468 100644 --- a/.gitignore +++ b/.gitignore @@ -36,6 +36,9 @@ test-output-acc.json # Taskfile cache .task/ +# Snapshot binary from 'task snapshot' +.databricks/ + # Built for 'task fmt' and yamlcheck.py in acceptance tests tools/yamlfmt tools/yamlfmt.exe diff --git a/AGENTS.md b/AGENTS.md index 1f90ac4104..256abd0442 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -28,9 +28,10 @@ When moving code from one place to another, please don't unnecessarily change th ### Specialized Commands -- `task schema` - Generate bundle JSON schema -- `task docs` - Generate bundle documentation -- `task generate` - Generate CLI code from OpenAPI spec (requires universe repo) +- `task generate:schema` - Generate bundle JSON schema +- `task generate:docs` - Generate bundle documentation +- `task generate:commands` - Generate CLI commands from OpenAPI spec (requires universe repo) +- `task generate` - Run all generators ### Git Commands diff --git a/Taskfile.yml b/Taskfile.yml index 2b632feacc..3701883fc1 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -4,8 +4,6 @@ vars: GO_TOOL: go tool -modfile=tools/go.mod TEST_PACKAGES: ./acceptance/internal ./libs/... ./internal/... ./cmd/... ./bundle/... ./experimental/ssh/... . ACCEPTANCE_TEST_FILTER: "" - MERGE_BASE: - sh: git merge-base main HEAD tasks: default: @@ -15,7 +13,7 @@ tasks: - task: fmt:full - task: lint:full - task: test - - task: schema + - task: generate:schema - task: generate:validation - task: python:lint - task: python:test @@ -470,22 +468,79 @@ tasks: - "deco env run -i -n aws-prod-ucws -- ./task dbr:integration" # --- Code generation --- + # + # Each generator declares tight `sources:` so Task's checksum cache re-runs only + # when inputs actually change. The reflection-based generators (schema, docs, + # validation) pick up SDK type changes via go.mod / go.sum. The aggregator + # `generate` orchestrates all of them; individual tasks can be invoked standalone. - schema: - desc: Generate bundle JSON schema (skipped if schema sources unchanged vs merge base) - status: - - git diff --quiet {{.MERGE_BASE}} -- bundle/internal/schema/ - - test -f bundle/schema/jsonschema.json + generate: + desc: Run all generators (CLI commands, schema, docs, validation, direct, python) + cmds: + # Runs first: may bump go.mod (SDK version), which invalidates reflection- + # based generators below so they re-run automatically. + - task: generate:commands + - task: generate:schema + - task: generate:schema-docs + - task: generate:validation + - task: generate:docs + - task: generate:direct + - task: python:codegen + + # Drives genkit from a universe checkout. Genkit writes CLI command files into + # cmd/workspace and cmd/account, bumps the SDK version in go.mod, and invokes + # tools/post-generate.sh (configured in .codegen.json) to post-process its + # output (tagging.py relocation, whitespace cleanup). + generate:commands: + desc: Generate CLI commands from OpenAPI spec (requires universe repo) + sources: + - .codegen/_openapi_sha + - .gitattributes.manual + - tools/post-generate.sh + vars: + UNIVERSE_DIR: + sh: echo "${UNIVERSE_DIR:-$HOME/universe}" + cmds: + - | + echo "Checking out universe at SHA: $(cat .codegen/_openapi_sha)" + cd {{.UNIVERSE_DIR}} && \ + git cat-file -e $(cat {{.ROOT_DIR}}/.codegen/_openapi_sha) 2>/dev/null || \ + (git fetch --filter=blob:none origin master && \ + git checkout $(cat {{.ROOT_DIR}}/.codegen/_openapi_sha)) + - echo "Building genkit..." + - cd {{.UNIVERSE_DIR}} && bazel build //openapi/genkit + - echo "Generating CLI code..." + - "{{.UNIVERSE_DIR}}/bazel-bin/openapi/genkit/genkit_/genkit update-sdk" + - "cat .gitattributes.manual .gitattributes > .gitattributes.tmp && mv .gitattributes.tmp .gitattributes" + - "-go test ./acceptance -run TestAccept/bundle/refschema -update &> /dev/null" + + generate:schema: + desc: Generate bundle JSON schema + sources: + - bundle/internal/schema/*.go + - exclude: bundle/internal/schema/*_test.go + - bundle/internal/schema/annotations*.yml + - bundle/config/**/*.go + - exclude: bundle/config/**/*_test.go + - libs/jsonschema/**/*.go + - exclude: libs/jsonschema/**/*_test.go + - go.mod + - go.sum + generates: + - bundle/schema/jsonschema.json cmds: - go run ./bundle/internal/schema ./bundle/internal/schema ./bundle/schema/jsonschema.json - schema:for-docs: + generate:schema-docs: desc: Generate bundle JSON schema for documentation sources: - bundle/internal/schema/*.go + - exclude: bundle/internal/schema/*_test.go - bundle/internal/schema/annotations*.yml - bundle/config/**/*.go + - exclude: bundle/config/**/*_test.go - libs/jsonschema/**/*.go + - exclude: libs/jsonschema/**/*_test.go - go.mod - go.sum generates: @@ -493,15 +548,19 @@ tasks: cmds: - go run ./bundle/internal/schema ./bundle/internal/schema ./bundle/schema/jsonschema_for_docs.json --docs - docs: + generate:docs: desc: Generate bundle documentation sources: - bundle/docsgen/*.go + - exclude: bundle/docsgen/*_test.go - bundle/docsgen/templates/** - bundle/internal/schema/annotations*.yml - bundle/internal/annotation/*.go + - exclude: bundle/internal/annotation/*_test.go - bundle/config/**/*.go + - exclude: bundle/config/**/*_test.go - libs/jsonschema/**/*.go + - exclude: libs/jsonschema/**/*_test.go - go.mod - go.sum generates: @@ -511,10 +570,18 @@ tasks: - go run ./bundle/docsgen ./bundle/internal/schema ./bundle/docsgen generate:validation: - desc: Generate enum and required field validation code (skipped if sources unchanged vs merge base) - status: - - git diff --quiet {{.MERGE_BASE}} -- bundle/internal/validation/ - - test -d bundle/internal/validation/generated + desc: Generate enum and required field validation code + sources: + - bundle/internal/validation/*.go + - exclude: bundle/internal/validation/*_test.go + - bundle/config/**/*.go + - exclude: bundle/config/**/*_test.go + - libs/structs/**/*.go + - exclude: libs/structs/**/*_test.go + - go.mod + - go.sum + generates: + - bundle/internal/validation/generated/**/*.go cmds: - go run ./bundle/internal/validation/. - gofmt -w -s ./bundle/internal/validation/generated @@ -524,7 +591,7 @@ tasks: deps: ['generate:direct-apitypes', 'generate:direct-resources'] generate:direct-apitypes: - deps: ['codegen:openapi-json'] + deps: ['generate:openapi-json'] sources: - bundle/direct/tools/generate_apitypes.py - .codegen/openapi.json @@ -562,29 +629,7 @@ tasks: cmds: - rm -f bundle/direct/dresources/apitypes.generated.yml bundle/direct/dresources/resources.generated.yml - generate: - desc: Generate CLI code from OpenAPI spec (requires universe repo) - vars: - UNIVERSE_DIR: - sh: echo "${UNIVERSE_DIR:-$HOME/universe}" - cmds: - - | - echo "Checking out universe at SHA: $(cat .codegen/_openapi_sha)" - cd {{.UNIVERSE_DIR}} && \ - git cat-file -e $(cat {{.ROOT_DIR}}/.codegen/_openapi_sha) 2>/dev/null || \ - (git fetch --filter=blob:none origin master && \ - git checkout $(cat {{.ROOT_DIR}}/.codegen/_openapi_sha)) - - echo "Building genkit..." - - cd {{.UNIVERSE_DIR}} && bazel build //openapi/genkit - - echo "Generating CLI code..." - - "{{.UNIVERSE_DIR}}/bazel-bin/openapi/genkit/genkit_/genkit update-sdk" - - "cat .gitattributes.manual .gitattributes > .gitattributes.tmp && mv .gitattributes.tmp .gitattributes" - - "-go test ./acceptance -run TestAccept/bundle/refschema -update &> /dev/null" - - echo "Updating direct engine config..." - - task: generate:direct - - go test ./bundle/internal/schema - - codegen:openapi-json: + generate:openapi-json: desc: Download OpenAPI spec (triggered by _openapi_sha change) sources: - .codegen/_openapi_sha diff --git a/bundle/docsgen/README.md b/bundle/docsgen/README.md index 220a14c1c9..a88e828ad4 100644 --- a/bundle/docsgen/README.md +++ b/bundle/docsgen/README.md @@ -1,14 +1,14 @@ ## docs-autogen 1. Install [Golang](https://go.dev/doc/install) -2. Run `make docs` from the repo +2. Run `task generate:docs` from the repo 3. See generated documents in `./bundle/docsgen/output` directory -4. To change descriptions update content in `./bundle/internal/schema/annotations.yml` or `./bundle/internal/schema/annotations_openapi_overrides.yml` and re-run `make docs` +4. To change descriptions update content in `./bundle/internal/schema/annotations.yml` or `./bundle/internal/schema/annotations_openapi_overrides.yml` and re-run `task generate:docs` For simpler usage run it together with copy command to move resulting files to local `docs` repo. Note that it will overwrite any local changes in affected files. Example: ``` -make docs && cp bundle/docgen/output/*.md ../docs/source/dev-tools/bundles +task generate:docs && cp bundle/docgen/output/*.md ../docs/source/dev-tools/bundles ``` To change intro sections for files update them in `templates/` directory @@ -76,4 +76,4 @@ github.com/databricks/cli/bundle/config.Bundle: ### TODO -Add file watcher to track changes in the annotation files and re-run `make docs` script automtically +Add file watcher to track changes in the annotation files and re-run `task generate:docs` script automtically diff --git a/bundle/internal/schema/main_test.go b/bundle/internal/schema/main_test.go index 1b655d2e16..fab75b7dbd 100644 --- a/bundle/internal/schema/main_test.go +++ b/bundle/internal/schema/main_test.go @@ -43,9 +43,9 @@ func copyFile(src, dst string) error { // Checks whether descriptions are added for new config fields in the annotations.yml file // If this test fails either manually add descriptions to the `annotations.yml` or do the following: // 1. for fields described outside of CLI package fetch latest schema from the OpenAPI spec and add path to file to DATABRICKS_OPENAPI_SPEC env variable -// 2. run `make schema` from the repository root to add placeholder descriptions +// 2. run `task generate:schema` from the repository root to add placeholder descriptions // 2. replace all "PLACEHOLDER" values with the actual descriptions if possible -// 3. run `make schema` again to regenerate the schema with acutal descriptions +// 3. run `task generate:schema` again to regenerate the schema with acutal descriptions func TestRequiredAnnotationsForNewFields(t *testing.T) { workdir := t.TempDir() annotationsPath := path.Join(workdir, "annotations.yml") diff --git a/tools/post-generate.sh b/tools/post-generate.sh index 4d65b70a35..065d110b9b 100755 --- a/tools/post-generate.sh +++ b/tools/post-generate.sh @@ -2,20 +2,16 @@ set -euxo pipefail +# This script runs inside `task generate:commands` via .codegen.json's +# `toolchain.post_generate`. It post-processes files that genkit just wrote +# (generated commands in cmd/, tagging.py, tagging.yml). Generators that read +# bundle config (schema, schema-for-docs, validation, docs) and Python codegen +# live as separate Taskfile tasks and run from the `generate` aggregator — go.mod +# being in their sources invalidates their caches when genkit bumps the SDK. + # Ensure the SDK version is consistent with the OpenAPI SHA the CLI is generated from. go test -timeout 240s -run TestConsistentDatabricksSdkVersion github.com/databricks/cli/internal/build -# Generate the bundle JSON schema. -make schema - -# Fetch version tags (required for make schema-for-docs). -git fetch origin 'refs/tags/v*:refs/tags/v*' - -make schema-for-docs - -# Generate bundle validation code for enuma and required fields. -make generate-validation - # Remove the next-changelog.yml workflow. rm .github/workflows/next-changelog.yml @@ -37,8 +33,5 @@ else fi go tool -modfile=tools/go.mod yamlfmt .github/workflows/tagging.yml -# Generate PyDABs code. -make -C python codegen - # Fix whitespace issues in the generated code. -make wsfix +./tools/validate_whitespace.py --fix From dcc8150b0d334847703889f0557ebdfdec2a9444 Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Sun, 19 Apr 2026 22:26:05 +0200 Subject: [PATCH 14/45] Split generate:refschema from generate:commands; wire generate into default - Move refschema regeneration into a standalone generate:refschema task with a tight sources list so the cache tracks what actually affects `bundle debug refschema` (cmd, dresources adapters, libs/structs, go.mod). - generate:commands now only runs genkit + post-process. - Aggregator runs generate:refschema between commands and the other generators so fresh out.fields.txt feeds generate:direct. - default now invokes the full generate aggregator instead of just generate:schema + generate:validation. - Fix acceptance/install_terraform.py to skip doc-comment lines when reading ProviderVersion (regressed by the recent doc comment added to bundle/internal/tf/codegen/schema/version.go). Co-authored-by: Isaac --- Taskfile.yml | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/Taskfile.yml b/Taskfile.yml index 3701883fc1..30e5950930 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -13,8 +13,7 @@ tasks: - task: fmt:full - task: lint:full - task: test - - task: generate:schema - - task: generate:validation + - task: generate - task: python:lint - task: python:test @@ -475,11 +474,14 @@ tasks: # `generate` orchestrates all of them; individual tasks can be invoked standalone. generate: - desc: Run all generators (CLI commands, schema, docs, validation, direct, python) + desc: Run all generators (CLI commands, refschema, schema, docs, validation, direct, python) cmds: # Runs first: may bump go.mod (SDK version), which invalidates reflection- # based generators below so they re-run automatically. - task: generate:commands + # Refreshes acceptance/bundle/refschema/out.fields.txt, which feeds + # generate:direct-apitypes and generate:direct-resources below. + - task: generate:refschema - task: generate:schema - task: generate:schema-docs - task: generate:validation @@ -512,7 +514,28 @@ tasks: - echo "Generating CLI code..." - "{{.UNIVERSE_DIR}}/bazel-bin/openapi/genkit/genkit_/genkit update-sdk" - "cat .gitattributes.manual .gitattributes > .gitattributes.tmp && mv .gitattributes.tmp .gitattributes" - - "-go test ./acceptance -run TestAccept/bundle/refschema -update &> /dev/null" + + # Refreshes out.fields.txt, which records the field paths / types emitted by + # `bundle debug refschema` (see cmd/bundle/debug/refschema.go). It reflects + # over the dresources adapter types, so sources list both the command and the + # adapter packages plus any SDK type changes (go.mod / go.sum). + generate:refschema: + desc: Regenerate acceptance/bundle/refschema/out.fields.txt + sources: + - cmd/bundle/debug/**/*.go + - exclude: cmd/bundle/debug/**/*_test.go + - bundle/direct/dresources/**/*.go + - exclude: bundle/direct/dresources/**/*_test.go + - libs/structs/**/*.go + - exclude: libs/structs/**/*_test.go + - acceptance/bundle/refschema/script + - acceptance/bundle/refschema/test.toml + - go.mod + - go.sum + generates: + - acceptance/bundle/refschema/out.fields.txt + cmds: + - go test ./acceptance -run TestAccept/bundle/refschema -update &> /dev/null generate:schema: desc: Generate bundle JSON schema From 8a76d2422c4aca91aee73d3c3728598b2d337acd Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Mon, 20 Apr 2026 11:17:16 +0200 Subject: [PATCH 15/45] Rename fmt/lint: drop :full, add -q suffix for quick variants MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Convention change: the plain task name is the full variant. Quick / incremental variants carry a -q suffix on the top-level namespace. - fmt:full -> fmt, fmt:go:full -> fmt:go (full is the default) - fmt (old incremental) -> fmt-q; fmt:go (old incremental) -> fmt-q:go - lint:full removed; lint is now the aggregator across all Go modules - lint (old incremental root+fix) -> lint-q:go:root; lint-q alias added - lint:go aggregator runs modules sequentially (concurrent golangci-lint invocations have shown unreliable behavior) - default task now runs the -q variants for a quick dev loop - new `all` task runs the full suite (checks, fmt, lint, test, generate, python:lint, python:test) — replaces old default semantics Close the gap where CI only linted the root module: CI now runs `./task lint` which covers root + tools + bundle/internal/tf/codegen. lintdiff.py gains --root-module to skip paths under nested go.mod files; needed for `golangci-lint run` (typechecks) but not for `fmt` (filesystem walk), so only lint-q:go:root opts in. Co-authored-by: Isaac --- .agent/skills/pr-checklist/SKILL.md | 22 ++++---- .github/workflows/check.yml | 6 +- AGENTS.md | 7 ++- Taskfile.yml | 88 ++++++++++++++++++----------- tools/lintdiff.py | 17 ++++++ 5 files changed, 89 insertions(+), 51 deletions(-) diff --git a/.agent/skills/pr-checklist/SKILL.md b/.agent/skills/pr-checklist/SKILL.md index c672e97757..65b82627b5 100644 --- a/.agent/skills/pr-checklist/SKILL.md +++ b/.agent/skills/pr-checklist/SKILL.md @@ -3,26 +3,26 @@ name: pr-checklist description: Checklist to run before submitting a PR --- -Before submitting a PR, run these commands to match what CI checks. CI uses the **full** variants (not the diff-only wrappers), so `make lint` alone is insufficient. +Before submitting a PR, run these commands to match what CI checks. CI uses the full variants (not the `-q` diff-only wrappers), so `./task lint-q` alone is insufficient. ```bash -# 1. Formatting and checks (CI runs fmtfull, not fmt) -make fmtfull -make checks +# 1. Formatting and checks (CI runs fmt, not fmt-q) +./task fmt +./task checks -# 2. Linting (CI runs full golangci-lint, not the diff-only wrapper) -make lintfull +# 2. Linting (CI runs full golangci-lint across all modules, not the diff-only wrapper) +./task lint # 3. Tests (CI runs with both deployment engines) -make test +./task test # 4. If you changed bundle config structs or schema-related code: -task generate:schema +./task generate:schema # 5. If you changed files in python/: -task python:codegen python:test python:lint python:docs +./task python:codegen python:test python:lint python:docs # 6. If you changed experimental/aitools or experimental/ssh: -make test-exp-aitools # only if aitools code changed -make test-exp-ssh # only if ssh code changed +./task test:exp-aitools # only if aitools code changed +./task test:exp-ssh # only if ssh code changed ``` diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index d4f603e751..1ce182801e 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -36,7 +36,7 @@ jobs: run: git diff --exit-code - name: Run Go lint checks (does not include formatting checks) - run: go tool -modfile=tools/go.mod golangci-lint run --timeout=15m + run: ./task lint - name: Run ruff (Python linter and formatter) uses: astral-sh/ruff-action@0ce1b0bf8b818ef400413f810f8a11cdbda0034b # v4.0.0 @@ -44,10 +44,10 @@ jobs: version: "0.9.1" args: "format --check" - - name: "task fmt:full: Python and Go formatting" + - name: "task fmt: Python and Go formatting" # Python formatting is already checked above, but this also checks Go and YAML formatting run: | - ./task fmt:full + ./task fmt git diff --exit-code - name: "task checks: custom checks outside of fmt and lint" diff --git a/AGENTS.md b/AGENTS.md index 256abd0442..a9403c6046 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -20,10 +20,11 @@ When moving code from one place to another, please don't unnecessarily change th ### Code Quality -- `task lint` - Run linter on changed files only (uses lintdiff.py) -- `task lint:full` - Run full linter with fixes (golangci-lint) +- `task lint` - Run full linter across all Go modules (root, tools, codegen) +- `task lint-q` - Run linter on changed files only (uses lintdiff.py, root module, with --fix) - `task ws` - Run whitespace linter -- `task fmt` - Format code (Go, Python, YAML) +- `task fmt` - Format all code (Go, Python, YAML) +- `task fmt-q` - Format changed files only (incremental Go + Python + YAML) - `task checks` - Run quick checks (tidy, whitespace, links) ### Specialized Commands diff --git a/Taskfile.yml b/Taskfile.yml index 30e5950930..7bfd6b649a 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -7,38 +7,54 @@ vars: tasks: default: - desc: Run all checks, fmt, lint, tests, and regeneration + desc: Quick dev loop (checks, formatters, incremental lint, tests). Use `all` for the full suite. cmds: - task: checks - - task: fmt:full - - task: lint:full + - task: fmt-q + - task: lint-q + - task: test + + all: + desc: Run all checks, full fmt, full lint, tests, and regeneration + cmds: + - task: checks + - task: fmt + - task: lint - task: test - task: generate - task: python:lint - task: python:test # --- Linting --- + # + # Naming convention: the plain name is the full variant (default). Quick + # / incremental variants carry a `-q` suffix on the top-level namespace + # (e.g. `lint-q:go:root`). `./task` (default) uses the -q variants for + # speed; `./task all` uses the full variants. lint: - desc: Lint changed Go files (root module, diff against main) - sources: - - "**/*.go" - - .golangci.yaml + desc: Lint all Go files (root + tools + codegen modules) cmds: - - ./tools/lintdiff.py go tool -modfile=tools/go.mod golangci-lint run --fix + - task: lint:go - lint:full: - desc: Lint all Go files with fixes (root module) - sources: - - "**/*.go" - - .golangci.yaml + lint-q: + desc: Lint changed Go files in root module (diff vs main, with --fix) cmds: - - go tool -modfile=tools/go.mod golangci-lint run --fix + - task: lint-q:go:root # `golangci-lint run` typechecks, so it stops at go.mod boundaries. We have # one task per Go module; `lint:go` composes them to cover the whole repo. + # Runs the modules sequentially because concurrent golangci-lint invocations + # have shown unreliable behavior. + lint:go: + desc: Lint Go files across all modules (root, tools, codegen) + cmds: + - task: lint:go:root + - task: lint:go:tools + - task: lint:go:codegen + lint:go:root: - desc: Lint Go files in the root module (no fixes) + desc: Lint Go files in the root module sources: - "**/*.go" - .golangci.yaml @@ -67,12 +83,24 @@ tasks: cmds: - go tool -modfile={{.ROOT_DIR}}/tools/go.mod golangci-lint run ./... - lint:go: - desc: Lint Go files across all modules (root, tools, codegen) - deps: ['lint:go:root', 'lint:go:tools', 'lint:go:codegen'] + lint-q:go:root: + desc: Lint changed Go files in root module (diff vs main, with --fix) + sources: + - "**/*.go" + - .golangci.yaml + cmds: + - ./tools/lintdiff.py --root-module go tool -modfile=tools/go.mod golangci-lint run --fix # --- Formatting --- + fmt: + desc: Format all files (Python, Go, YAML) + deps: ['fmt:python', 'fmt:go', 'fmt:yaml'] + + fmt-q: + desc: Format changed files (Python, incremental Go, YAML) + deps: ['fmt:python', 'fmt-q:go', 'fmt:yaml'] + fmt:python: desc: Format Python files sources: @@ -80,24 +108,24 @@ tasks: cmds: - ruff format -n + # `golangci-lint fmt` walks the filesystem and doesn't typecheck, so it + # formats files across all nested modules (tools/, bundle/internal/tf/codegen/) + # in a single invocation. fmt:go: - desc: Format changed Go files (diff vs main) + desc: Format all Go files sources: - "**/*.go" - .golangci.yaml cmds: - - ./tools/lintdiff.py go tool -modfile=tools/go.mod golangci-lint fmt + - go tool -modfile=tools/go.mod golangci-lint fmt - # `golangci-lint fmt` walks the filesystem and doesn't typecheck, so it - # formats files across all nested modules (tools/, bundle/internal/tf/codegen/) - # in a single invocation. - fmt:go:full: - desc: Format all Go files + fmt-q:go: + desc: Format changed Go files (diff vs main) sources: - "**/*.go" - .golangci.yaml cmds: - - go tool -modfile=tools/go.mod golangci-lint fmt + - ./tools/lintdiff.py go tool -modfile=tools/go.mod golangci-lint fmt fmt:yaml: desc: Format YAML files @@ -108,14 +136,6 @@ tasks: cmds: - go tool -modfile=tools/go.mod yamlfmt . - fmt: - desc: Format changed files (Python, incremental Go, YAML) - deps: ['fmt:python', 'fmt:go', 'fmt:yaml'] - - fmt:full: - desc: Format all files (Python, full Go, YAML) - deps: ['fmt:python', 'fmt:go:full', 'fmt:yaml'] - # --- Code checks --- tidy: diff --git a/tools/lintdiff.py b/tools/lintdiff.py index 77b9ee6f51..e10540c69d 100755 --- a/tools/lintdiff.py +++ b/tools/lintdiff.py @@ -28,6 +28,12 @@ def main(): parser.add_argument( "-H", "--head", action="store_true", help="Shortcut for '--ref HEAD' - test uncommitted changes only" ) + parser.add_argument( + "--root-module", + action="store_true", + help="Only include paths in the root Go module (skip subtrees under nested go.mod files). " + "Needed for `golangci-lint run` because it typechecks and fails on paths outside its module.", + ) parser.add_argument("args", nargs=argparse.REMAINDER, help="golangci-lint command and options") args = parser.parse_args() @@ -53,6 +59,15 @@ def main(): cmd = args.args[:] if changed is not None: + nested_modules = [] + if args.root_module: + nested_modules = sorted( + os.path.dirname(p) for p in parse_lines(["git", "ls-files", "--", "*/go.mod"]) or [] + ) + + def in_nested_module(path): + return any(path == m or path.startswith(m + "/") for m in nested_modules) + # We need to pass packages to golangci-lint, not individual files. # QQQ for lint we should also pass all dependent packages dirs = set() @@ -61,6 +76,8 @@ def main(): continue if filename.endswith(".go"): d = os.path.dirname(filename) + if in_nested_module(d): + continue dirs.add(d) dirs = ["./" + d for d in sorted(dirs) if os.path.exists(d)] From 654a96df125eeae850f65ca6b10592c9cc3d1256 Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Mon, 20 Apr 2026 11:19:06 +0200 Subject: [PATCH 16/45] lintdiff: auto-detect when to filter nested modules Drop the --root-module flag; infer from the wrapped subcommand instead. `golangci-lint run` typechecks and needs the filter; `golangci-lint fmt` walks the filesystem and wants to see changed files across modules. Callers no longer need to know which mode applies. Co-authored-by: Isaac --- Taskfile.yml | 2 +- tools/lintdiff.py | 13 ++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/Taskfile.yml b/Taskfile.yml index 7bfd6b649a..0cebaba8be 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -89,7 +89,7 @@ tasks: - "**/*.go" - .golangci.yaml cmds: - - ./tools/lintdiff.py --root-module go tool -modfile=tools/go.mod golangci-lint run --fix + - ./tools/lintdiff.py go tool -modfile=tools/go.mod golangci-lint run --fix # --- Formatting --- diff --git a/tools/lintdiff.py b/tools/lintdiff.py index e10540c69d..8c6092f9e4 100755 --- a/tools/lintdiff.py +++ b/tools/lintdiff.py @@ -28,12 +28,6 @@ def main(): parser.add_argument( "-H", "--head", action="store_true", help="Shortcut for '--ref HEAD' - test uncommitted changes only" ) - parser.add_argument( - "--root-module", - action="store_true", - help="Only include paths in the root Go module (skip subtrees under nested go.mod files). " - "Needed for `golangci-lint run` because it typechecks and fails on paths outside its module.", - ) parser.add_argument("args", nargs=argparse.REMAINDER, help="golangci-lint command and options") args = parser.parse_args() @@ -58,9 +52,14 @@ def main(): cmd = args.args[:] + # `golangci-lint run` typechecks against the target go.mod and errors on + # paths under a different module; `fmt` walks the filesystem and is + # cross-module safe. Apply the nested-module filter only for `run`. + filter_nested = "run" in cmd + if changed is not None: nested_modules = [] - if args.root_module: + if filter_nested: nested_modules = sorted( os.path.dirname(p) for p in parse_lines(["git", "ls-files", "--", "*/go.mod"]) or [] ) From c5097f621a454d5dfabf4f205e80bec43179b8ae Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Mon, 20 Apr 2026 15:04:57 +0200 Subject: [PATCH 17/45] Taskfile: skip generate:commands in `./task all` generate:commands is expensive (bazel/genkit build) and requires a universe checkout. Its outputs are committed, so a fresh worktree at any commit already has them. Run `./task generate` explicitly when codegen inputs change. Co-authored-by: Isaac --- Taskfile.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Taskfile.yml b/Taskfile.yml index 0cebaba8be..fb3f44f42e 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -21,7 +21,15 @@ tasks: - task: fmt - task: lint - task: test - - task: generate + # Skips generate:commands (expensive, requires universe checkout, outputs are + # committed). Run `./task generate` explicitly when codegen inputs change. + - task: generate:refschema + - task: generate:schema + - task: generate:schema-docs + - task: generate:validation + - task: generate:docs + - task: generate:direct + - task: python:codegen - task: python:lint - task: python:test From 23051bcdd59e976d8fd0a9bc1583243e060d97b8 Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Mon, 20 Apr 2026 16:21:02 +0200 Subject: [PATCH 18/45] Taskfile: consistency fixes from review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Use {{.GO_TOOL}} everywhere (redefine with {{.ROOT_DIR}} so tasks with `dir:` can reference it). - Drop dead `{{.X | default ...}}` fallbacks in task-local vars; the top-level vars are always set and pass through via `deps:` + `vars:`. - Serialize `checks` (tidy/ws/links) and `test:update-all` — they were racing on the same files via parallel `deps:`. - Add `deps: [tidy]` to `snapshot` and `snapshot:release` (matches `build`). - Add `desc:` to `generate:direct-apitypes` and `generate:direct-resources`. - Expand `lint-q:go:root` desc to note it skips tools/ and codegen/. - Drop `sources:` from `ws` (script is fast; no point caching). - Fix code-generation section comment to list all reflection-based generators (refschema, schema-docs missing). Co-authored-by: Isaac --- Taskfile.yml | 59 +++++++++++++++++++++++++--------------------------- 1 file changed, 28 insertions(+), 31 deletions(-) diff --git a/Taskfile.yml b/Taskfile.yml index fb3f44f42e..6f6877335b 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -1,7 +1,8 @@ version: '3' vars: - GO_TOOL: go tool -modfile=tools/go.mod + # Absolute path so tasks with `dir:` (lint:go:tools, lint:go:codegen) can use it. + GO_TOOL: go tool -modfile={{.ROOT_DIR}}/tools/go.mod TEST_PACKAGES: ./acceptance/internal ./libs/... ./internal/... ./cmd/... ./bundle/... ./experimental/ssh/... . ACCEPTANCE_TEST_FILTER: "" @@ -67,7 +68,7 @@ tasks: - "**/*.go" - .golangci.yaml cmds: - - go tool -modfile=tools/go.mod golangci-lint run ./... + - "{{.GO_TOOL}} golangci-lint run ./..." lint:go:tools: desc: Lint Go files in tools/ module @@ -78,7 +79,7 @@ tasks: - go.mod - go.sum cmds: - - go tool -modfile={{.ROOT_DIR}}/tools/go.mod golangci-lint run ./... + - "{{.GO_TOOL}} golangci-lint run ./..." lint:go:codegen: desc: Lint Go files in bundle/internal/tf/codegen module @@ -89,15 +90,15 @@ tasks: - go.mod - go.sum cmds: - - go tool -modfile={{.ROOT_DIR}}/tools/go.mod golangci-lint run ./... + - "{{.GO_TOOL}} golangci-lint run ./..." lint-q:go:root: - desc: Lint changed Go files in root module (diff vs main, with --fix) + desc: Lint changed Go files in root module (diff vs main, with --fix). Does not check tools/ or bundle/internal/tf/codegen — use `lint` for full coverage. sources: - "**/*.go" - .golangci.yaml cmds: - - ./tools/lintdiff.py go tool -modfile=tools/go.mod golangci-lint run --fix + - "./tools/lintdiff.py {{.GO_TOOL}} golangci-lint run --fix" # --- Formatting --- @@ -125,7 +126,7 @@ tasks: - "**/*.go" - .golangci.yaml cmds: - - go tool -modfile=tools/go.mod golangci-lint fmt + - "{{.GO_TOOL}} golangci-lint fmt" fmt-q:go: desc: Format changed Go files (diff vs main) @@ -133,7 +134,7 @@ tasks: - "**/*.go" - .golangci.yaml cmds: - - ./tools/lintdiff.py go tool -modfile=tools/go.mod golangci-lint fmt + - "./tools/lintdiff.py {{.GO_TOOL}} golangci-lint fmt" fmt:yaml: desc: Format YAML files @@ -142,7 +143,7 @@ tasks: - "**/*.yaml" - yamlfmt.yml cmds: - - go tool -modfile=tools/go.mod yamlfmt . + - "{{.GO_TOOL}} yamlfmt ." # --- Code checks --- @@ -157,12 +158,6 @@ tasks: ws: desc: Check whitespace - sources: - - "**/*.go" - - "**/*.py" - - "**/*.yml" - - "**/*.yaml" - - "**/*.md" cmds: - ./tools/validate_whitespace.py @@ -180,7 +175,12 @@ tasks: checks: desc: Run quick checks (tidy, whitespace, links) - deps: [tidy, ws, links] + # Sequential: `tidy` rewrites go.mod/go.sum and any future tidy work + # touching more paths should not race with whitespace/link scanners. + cmds: + - task: tidy + - task: ws + - task: links install-pythons: desc: Install Python 3.9-3.13 via uv @@ -211,6 +211,7 @@ tasks: snapshot: desc: Build snapshot binary to .databricks/databricks + deps: [tidy] sources: - "**/*.go" - exclude: "**/*_test.go" @@ -227,6 +228,7 @@ tasks: snapshot:release: desc: Build release binaries locally without uploading + deps: [tidy] sources: - "**/*.go" - exclude: "**/*_test.go" @@ -272,8 +274,6 @@ tasks: desc: Run short unit tests sources: - "**/*.go" - vars: - TEST_PACKAGES: '{{.TEST_PACKAGES | default "./acceptance/internal ./libs/... ./internal/... ./cmd/... ./bundle/... ./experimental/ssh/... ."}}' cmds: - | {{.GO_TOOL}} gotestsum \ @@ -288,8 +288,6 @@ tasks: desc: Run all unit tests (no -short) sources: - "**/*.go" - vars: - TEST_PACKAGES: '{{.TEST_PACKAGES | default "./acceptance/internal ./libs/... ./internal/... ./cmd/... ./bundle/... ./experimental/ssh/... ."}}' cmds: - | {{.GO_TOOL}} gotestsum \ @@ -305,8 +303,6 @@ tasks: sources: - "**/*.go" - acceptance/** - vars: - ACCEPTANCE_TEST_FILTER: '{{.ACCEPTANCE_TEST_FILTER | default ""}}' cmds: - | {{.GO_TOOL}} gotestsum \ @@ -322,8 +318,6 @@ tasks: sources: - "**/*.go" - acceptance/** - vars: - ACCEPTANCE_TEST_FILTER: '{{.ACCEPTANCE_TEST_FILTER | default ""}}' cmds: - | {{.GO_TOOL}} gotestsum \ @@ -351,7 +345,10 @@ tasks: test:update-all: desc: Update all acceptance test outputs - deps: ['test:update', 'test:update-aws'] + # Sequential: both tasks overwrite the same acceptance output files. + cmds: + - task: test:update + - task: test:update-aws generate:out-test-toml: desc: Regenerate out.test.toml files without running tests @@ -365,9 +362,6 @@ tasks: cover: desc: Run tests with coverage - vars: - ACCEPTANCE_TEST_FILTER: '{{.ACCEPTANCE_TEST_FILTER | default ""}}' - TEST_PACKAGES: '{{.TEST_PACKAGES | default "./acceptance/internal ./libs/... ./internal/... ./cmd/... ./bundle/... ./experimental/ssh/... ."}}' cmds: - rm -fr ./acceptance/build/cover/ - | @@ -497,9 +491,10 @@ tasks: # --- Code generation --- # # Each generator declares tight `sources:` so Task's checksum cache re-runs only - # when inputs actually change. The reflection-based generators (schema, docs, - # validation) pick up SDK type changes via go.mod / go.sum. The aggregator - # `generate` orchestrates all of them; individual tasks can be invoked standalone. + # when inputs actually change. The reflection-based generators (refschema, + # schema, schema-docs, docs, validation) pick up SDK type changes via go.mod / + # go.sum. The aggregator `generate` orchestrates all of them; individual tasks + # can be invoked standalone. generate: desc: Run all generators (CLI commands, refschema, schema, docs, validation, direct, python) @@ -642,6 +637,7 @@ tasks: deps: ['generate:direct-apitypes', 'generate:direct-resources'] generate:direct-apitypes: + desc: Generate direct engine API types YAML deps: ['generate:openapi-json'] sources: - bundle/direct/tools/generate_apitypes.py @@ -657,6 +653,7 @@ tasks: > bundle/direct/dresources/apitypes.generated.yml generate:direct-resources: + desc: Generate direct engine resources YAML deps: ['generate:direct-apitypes'] sources: - bundle/direct/tools/generate_resources.py From a3431df5259c4b6b8304885d49b73785d4133db1 Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Mon, 20 Apr 2026 17:27:39 +0200 Subject: [PATCH 19/45] Taskfile: tidy/lint cache precision and multi-module tidy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `lint:go:root` and `lint-q:go:root` now exclude tools/** and bundle/internal/tf/codegen/** from sources. golangci-lint `./...` stops at module boundaries, so changes there never affect root-module lint output — no reason to invalidate the cache. - Split `tidy` by module, matching the `lint:go` layout: - `tidy` — aggregator across all three modules - `tidy:root` — root (previously `tidy`) - `tidy:tools` — tools/ - `tidy:codegen` — bundle/internal/tf/codegen `build`, `snapshot`, `snapshot:release` switch to `deps: [tidy:root]` (they only build the root module); `checks` still calls the aggregator. Co-authored-by: Isaac --- Taskfile.yml | 41 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/Taskfile.yml b/Taskfile.yml index 6f6877335b..af03459add 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -66,6 +66,8 @@ tasks: desc: Lint Go files in the root module sources: - "**/*.go" + - exclude: tools/** + - exclude: bundle/internal/tf/codegen/** - .golangci.yaml cmds: - "{{.GO_TOOL}} golangci-lint run ./..." @@ -96,6 +98,8 @@ tasks: desc: Lint changed Go files in root module (diff vs main, with --fix). Does not check tools/ or bundle/internal/tf/codegen — use `lint` for full coverage. sources: - "**/*.go" + - exclude: tools/** + - exclude: bundle/internal/tf/codegen/** - .golangci.yaml cmds: - "./tools/lintdiff.py {{.GO_TOOL}} golangci-lint run --fix" @@ -148,7 +152,36 @@ tasks: # --- Code checks --- tidy: - desc: Run go mod tidy + desc: Run go mod tidy across all Go modules (root, tools, codegen) + cmds: + - task: tidy:root + - task: tidy:tools + - task: tidy:codegen + + tidy:root: + desc: Run go mod tidy in root module + sources: + - go.mod + - go.sum + - "**/*.go" + - exclude: tools/** + - exclude: bundle/internal/tf/codegen/** + cmds: + - go mod tidy + + tidy:tools: + desc: Run go mod tidy in tools/ module + dir: tools + sources: + - go.mod + - go.sum + - "**/*.go" + cmds: + - go mod tidy + + tidy:codegen: + desc: Run go mod tidy in bundle/internal/tf/codegen module + dir: bundle/internal/tf/codegen sources: - go.mod - go.sum @@ -194,7 +227,7 @@ tasks: # (tools/, bundle/internal/tf/codegen/), and _test.go files don't affect the build. build: desc: Build the CLI binary - deps: [tidy] + deps: [tidy:root] sources: - "**/*.go" - exclude: "**/*_test.go" @@ -211,7 +244,7 @@ tasks: snapshot: desc: Build snapshot binary to .databricks/databricks - deps: [tidy] + deps: [tidy:root] sources: - "**/*.go" - exclude: "**/*_test.go" @@ -228,7 +261,7 @@ tasks: snapshot:release: desc: Build release binaries locally without uploading - deps: [tidy] + deps: [tidy:root] sources: - "**/*.go" - exclude: "**/*_test.go" From 63c4c0b626e1152252a3ac69746eddd6c207305c Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Mon, 20 Apr 2026 18:15:10 +0200 Subject: [PATCH 20/45] Taskfile: remove Slow test variants Mirrors main's e24ae4ec7 (Remove Slow tests #5032): drop test:slow, test:slow-unit, test:slow-acc, and the `-short` flag from test:unit and test:acc. Slow tests support in the acceptance runner was removed because the split between short and fast tests adds complexity and makes it possible to miss failures. Co-authored-by: Isaac --- Taskfile.yml | 47 +++-------------------------------------------- 1 file changed, 3 insertions(+), 44 deletions(-) diff --git a/Taskfile.yml b/Taskfile.yml index af03459add..5ad9baf928 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -280,7 +280,7 @@ tasks: # --- Testing --- test: - desc: Run short unit and acceptance tests (in parallel) + desc: Run unit and acceptance tests (in parallel) deps: - task: test:unit vars: @@ -291,34 +291,8 @@ tasks: cmds: - cat test-output-unit.json test-output-acc.json > test-output.json - test:slow: - desc: Run all unit and acceptance tests (in parallel, no -short) - deps: - - task: test:slow-unit - vars: - TEST_PACKAGES: "{{.TEST_PACKAGES}}" - - task: test:slow-acc - vars: - ACCEPTANCE_TEST_FILTER: "{{.ACCEPTANCE_TEST_FILTER}}" - cmds: - - cat test-output-unit.json test-output-acc.json > test-output.json - test:unit: - desc: Run short unit tests - sources: - - "**/*.go" - cmds: - - | - {{.GO_TOOL}} gotestsum \ - --format ${GOTESTSUM_FORMAT:-pkgname-and-test-fails} \ - --no-summary=skipped \ - --jsonfile test-output-unit.json \ - --rerun-fails \ - --packages "{{.TEST_PACKAGES}}" \ - -- -timeout=${LOCAL_TIMEOUT:-30m} -short - - test:slow-unit: - desc: Run all unit tests (no -short) + desc: Run unit tests sources: - "**/*.go" cmds: @@ -332,22 +306,7 @@ tasks: -- -timeout=${LOCAL_TIMEOUT:-30m} test:acc: - desc: Run short acceptance tests - sources: - - "**/*.go" - - acceptance/** - cmds: - - | - {{.GO_TOOL}} gotestsum \ - --format ${GOTESTSUM_FORMAT:-pkgname-and-test-fails} \ - --no-summary=skipped \ - --jsonfile test-output-acc.json \ - --rerun-fails \ - --packages ./acceptance/... \ - -- -timeout=${LOCAL_TIMEOUT:-30m} -short{{if .ACCEPTANCE_TEST_FILTER}} -run "{{.ACCEPTANCE_TEST_FILTER}}"{{end}} - - test:slow-acc: - desc: Run all acceptance tests (no -short) + desc: Run acceptance tests sources: - "**/*.go" - acceptance/** From 2564a7abba0c722e5a6ebca393fced048b7e54bb Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Mon, 20 Apr 2026 18:17:38 +0200 Subject: [PATCH 21/45] Taskfile: run lint:go and tidy in parallel via deps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Switch lint:go and tidy aggregators from sequential cmds: to parallel deps:. Each lint:go module sets its own TMPDIR under .tmp/ so concurrent golangci-lint invocations — both siblings here and sibling worktrees running lint at the same time — don't serialize on the shared /tmp lock. The TMPDIR path lives under the repo (but not at ROOT_DIR itself, which would trip Go's "go.mod in os.TempDir" check). Add /.tmp/ to .gitignore. Co-authored-by: Isaac --- .gitignore | 1 + Taskfile.yml | 50 +++++++++++++++++++++++++++++++++----------------- 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/.gitignore b/.gitignore index 9356630468..179a4d18fc 100644 --- a/.gitignore +++ b/.gitignore @@ -58,6 +58,7 @@ dist/ # Local development notes, tmp /pr-* /tmp/ +/.tmp/ # Go workspace file go.work diff --git a/Taskfile.yml b/Taskfile.yml index 5ad9baf928..6cd2dfeb75 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -53,56 +53,75 @@ tasks: # `golangci-lint run` typechecks, so it stops at go.mod boundaries. We have # one task per Go module; `lint:go` composes them to cover the whole repo. - # Runs the modules sequentially because concurrent golangci-lint invocations - # have shown unreliable behavior. + # Children run in parallel — each uses its own TMPDIR (set inline on the + # golangci-lint command below) to avoid the shared /tmp lock that serializes + # concurrent golangci-lint invocations. This matters in two scenarios: + # 1. siblings of `lint:go` running in parallel on subprojects here, and + # 2. `lint:go` invocations in sibling worktrees running at the same time. + # The TMPDIR must live under the repo but NOT equal {{.ROOT_DIR}} itself + # (the Go toolchain refuses a go.mod inside os.TempDir, which would break + # golangci-lint's typechecker). lint:go: desc: Lint Go files across all modules (root, tools, codegen) - cmds: - - task: lint:go:root - - task: lint:go:tools - - task: lint:go:codegen + deps: ['lint:go:root', 'lint:go:tools', 'lint:go:codegen'] lint:go:root: desc: Lint Go files in the root module + vars: + TMPDIR: '{{.ROOT_DIR}}/.tmp/golangci-lint-root' sources: - "**/*.go" - exclude: tools/** - exclude: bundle/internal/tf/codegen/** - .golangci.yaml cmds: - - "{{.GO_TOOL}} golangci-lint run ./..." + - cmd: mkdir -p "{{.TMPDIR}}" + silent: true + - TMPDIR="{{.TMPDIR}}" {{.GO_TOOL}} golangci-lint run ./... lint:go:tools: desc: Lint Go files in tools/ module dir: tools + vars: + TMPDIR: '{{.ROOT_DIR}}/.tmp/golangci-lint-tools' sources: - "**/*.go" - .golangci.yaml - go.mod - go.sum cmds: - - "{{.GO_TOOL}} golangci-lint run ./..." + - cmd: mkdir -p "{{.TMPDIR}}" + silent: true + - TMPDIR="{{.TMPDIR}}" {{.GO_TOOL}} golangci-lint run ./... lint:go:codegen: desc: Lint Go files in bundle/internal/tf/codegen module dir: bundle/internal/tf/codegen + vars: + TMPDIR: '{{.ROOT_DIR}}/.tmp/golangci-lint-codegen' sources: - "**/*.go" - .golangci.yaml - go.mod - go.sum cmds: - - "{{.GO_TOOL}} golangci-lint run ./..." + - cmd: mkdir -p "{{.TMPDIR}}" + silent: true + - TMPDIR="{{.TMPDIR}}" {{.GO_TOOL}} golangci-lint run ./... lint-q:go:root: desc: Lint changed Go files in root module (diff vs main, with --fix). Does not check tools/ or bundle/internal/tf/codegen — use `lint` for full coverage. + vars: + TMPDIR: '{{.ROOT_DIR}}/.tmp/golangci-lint-root' sources: - "**/*.go" - exclude: tools/** - exclude: bundle/internal/tf/codegen/** - .golangci.yaml cmds: - - "./tools/lintdiff.py {{.GO_TOOL}} golangci-lint run --fix" + - cmd: mkdir -p "{{.TMPDIR}}" + silent: true + - TMPDIR="{{.TMPDIR}}" ./tools/lintdiff.py {{.GO_TOOL}} golangci-lint run --fix # --- Formatting --- @@ -153,10 +172,7 @@ tasks: tidy: desc: Run go mod tidy across all Go modules (root, tools, codegen) - cmds: - - task: tidy:root - - task: tidy:tools - - task: tidy:codegen + deps: ['tidy:root', 'tidy:tools', 'tidy:codegen'] tidy:root: desc: Run go mod tidy in root module @@ -227,7 +243,7 @@ tasks: # (tools/, bundle/internal/tf/codegen/), and _test.go files don't affect the build. build: desc: Build the CLI binary - deps: [tidy:root] + deps: ['tidy:root'] sources: - "**/*.go" - exclude: "**/*_test.go" @@ -244,7 +260,7 @@ tasks: snapshot: desc: Build snapshot binary to .databricks/databricks - deps: [tidy:root] + deps: ['tidy:root'] sources: - "**/*.go" - exclude: "**/*_test.go" @@ -261,7 +277,7 @@ tasks: snapshot:release: desc: Build release binaries locally without uploading - deps: [tidy:root] + deps: ['tidy:root'] sources: - "**/*.go" - exclude: "**/*_test.go" From 63b574f4199e23a67e88d5e4e01728ed38e62fab Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Mon, 20 Apr 2026 18:18:19 +0200 Subject: [PATCH 22/45] Taskfile: namespace generate:direct subtasks with colon MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename generate:direct-{apitypes,resources,clean} to generate:direct:{apitypes,resources,clean} so the direct engine subtasks follow the same colon-namespaced convention as lint:go:root, tidy:root, etc. Also broaden generate:refschema sources to all of bundle/ (excluding _test.go) plus go.mod / go.sum — the command reflects over types reachable from bundle/, so narrowing to a handful of packages risks missing changes that affect the schema. Co-authored-by: Isaac --- .agent/rules/auto-generated-files.md | 2 +- Taskfile.yml | 24 ++++++++++-------------- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/.agent/rules/auto-generated-files.md b/.agent/rules/auto-generated-files.md index e2ace0def5..1c96544b06 100644 --- a/.agent/rules/auto-generated-files.md +++ b/.agent/rules/auto-generated-files.md @@ -69,7 +69,7 @@ If a change is needed in any matched file: - `task generate:commands` - Includes generated `cmd/account/**`, `cmd/workspace/**`, `.gitattributes`, `internal/genkit/tagging.py`. - Direct engine generated YAML: - - `task generate:direct` (or `task generate:direct-apitypes`, `task generate:direct-resources`) + - `task generate:direct` (or `task generate:direct:apitypes`, `task generate:direct:resources`) - Bundle schemas: - `task generate:schema` - `task generate:schema-docs` diff --git a/Taskfile.yml b/Taskfile.yml index 6cd2dfeb75..eab5ade50a 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -511,7 +511,7 @@ tasks: # based generators below so they re-run automatically. - task: generate:commands # Refreshes acceptance/bundle/refschema/out.fields.txt, which feeds - # generate:direct-apitypes and generate:direct-resources below. + # generate:direct:apitypes and generate:direct:resources below. - task: generate:refschema - task: generate:schema - task: generate:schema-docs @@ -548,17 +548,13 @@ tasks: # Refreshes out.fields.txt, which records the field paths / types emitted by # `bundle debug refschema` (see cmd/bundle/debug/refschema.go). It reflects - # over the dresources adapter types, so sources list both the command and the - # adapter packages plus any SDK type changes (go.mod / go.sum). + # over types reachable from bundle/, so any bundle change or SDK bump (go.mod + # / go.sum) can affect the output. generate:refschema: desc: Regenerate acceptance/bundle/refschema/out.fields.txt sources: - - cmd/bundle/debug/**/*.go - - exclude: cmd/bundle/debug/**/*_test.go - - bundle/direct/dresources/**/*.go - - exclude: bundle/direct/dresources/**/*_test.go - - libs/structs/**/*.go - - exclude: libs/structs/**/*_test.go + - bundle/**/*.go + - exclude: bundle/**/*_test.go - acceptance/bundle/refschema/script - acceptance/bundle/refschema/test.toml - go.mod @@ -642,9 +638,9 @@ tasks: generate:direct: desc: Generate direct engine config (apitypes + resources) - deps: ['generate:direct-apitypes', 'generate:direct-resources'] + deps: ['generate:direct:apitypes', 'generate:direct:resources'] - generate:direct-apitypes: + generate:direct:apitypes: desc: Generate direct engine API types YAML deps: ['generate:openapi-json'] sources: @@ -660,9 +656,9 @@ tasks: acceptance/bundle/refschema/out.fields.txt > bundle/direct/dresources/apitypes.generated.yml - generate:direct-resources: + generate:direct:resources: desc: Generate direct engine resources YAML - deps: ['generate:direct-apitypes'] + deps: ['generate:direct:apitypes'] sources: - bundle/direct/tools/generate_resources.py - .codegen/openapi.json @@ -680,7 +676,7 @@ tasks: acceptance/bundle/refschema/out.fields.txt > bundle/direct/dresources/resources.generated.yml - generate:direct-clean: + generate:direct:clean: desc: Remove generated direct engine files cmds: - rm -f bundle/direct/dresources/apitypes.generated.yml bundle/direct/dresources/resources.generated.yml From 4358d7a254ba27eb15d56979c2562181c614c360 Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Mon, 20 Apr 2026 18:28:28 +0200 Subject: [PATCH 23/45] Taskfile: rename generate:commands to generate:genkit, inline post-generate.sh Renamed because the task does more than generate CLI commands: it also emits the tagging workflow + tagging.py, bumps the SDK version, and post-processes the output. Moved the steps from tools/post-generate.sh (previously invoked via .codegen.json post_generate hook) inline into the task so ./task generate is self-contained and the tree is left clean afterwards. Also dropped generate:direct:clean which was out of place. Co-authored-by: Isaac --- .agent/rules/auto-generated-files.md | 2 +- .codegen.json | 3 --- AGENTS.md | 2 +- Taskfile.yml | 38 ++++++++++++++++++---------- tools/post-generate.sh | 37 --------------------------- 5 files changed, 26 insertions(+), 56 deletions(-) delete mode 100755 tools/post-generate.sh diff --git a/.agent/rules/auto-generated-files.md b/.agent/rules/auto-generated-files.md index 1c96544b06..1ac4450a45 100644 --- a/.agent/rules/auto-generated-files.md +++ b/.agent/rules/auto-generated-files.md @@ -66,7 +66,7 @@ If a change is needed in any matched file: - Everything, in one shot: - `task generate` — aggregator that runs all generators below - OpenAPI SDK/CLI command stubs and related generated artifacts: - - `task generate:commands` + - `task generate:genkit` - Includes generated `cmd/account/**`, `cmd/workspace/**`, `.gitattributes`, `internal/genkit/tagging.py`. - Direct engine generated YAML: - `task generate:direct` (or `task generate:direct:apitypes`, `task generate:direct:resources`) diff --git a/.codegen.json b/.codegen.json index b8bb2b3ec5..e2a84cb8c1 100644 --- a/.codegen.json +++ b/.codegen.json @@ -12,9 +12,6 @@ "toolchain": { "required": [ "go" - ], - "post_generate": [ - "./tools/post-generate.sh" ] } } diff --git a/AGENTS.md b/AGENTS.md index a9403c6046..053d43ae58 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -31,7 +31,7 @@ When moving code from one place to another, please don't unnecessarily change th - `task generate:schema` - Generate bundle JSON schema - `task generate:docs` - Generate bundle documentation -- `task generate:commands` - Generate CLI commands from OpenAPI spec (requires universe repo) +- `task generate:genkit` - Run genkit to generate CLI commands and tagging workflow (requires universe repo) - `task generate` - Run all generators ### Git Commands diff --git a/Taskfile.yml b/Taskfile.yml index eab5ade50a..5f35ee5352 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -22,7 +22,7 @@ tasks: - task: fmt - task: lint - task: test - # Skips generate:commands (expensive, requires universe checkout, outputs are + # Skips generate:genkit (expensive, requires universe checkout, outputs are # committed). Run `./task generate` explicitly when codegen inputs change. - task: generate:refschema - task: generate:schema @@ -505,11 +505,11 @@ tasks: # can be invoked standalone. generate: - desc: Run all generators (CLI commands, refschema, schema, docs, validation, direct, python) + desc: Run all generators (genkit, refschema, schema, docs, validation, direct, pydabs) cmds: # Runs first: may bump go.mod (SDK version), which invalidates reflection- # based generators below so they re-run automatically. - - task: generate:commands + - task: generate:genkit # Refreshes acceptance/bundle/refschema/out.fields.txt, which feeds # generate:direct:apitypes and generate:direct:resources below. - task: generate:refschema @@ -521,15 +521,18 @@ tasks: - task: python:codegen # Drives genkit from a universe checkout. Genkit writes CLI command files into - # cmd/workspace and cmd/account, bumps the SDK version in go.mod, and invokes - # tools/post-generate.sh (configured in .codegen.json) to post-process its - # output (tagging.py relocation, whitespace cleanup). - generate:commands: - desc: Generate CLI commands from OpenAPI spec (requires universe repo) + # cmd/workspace and cmd/account, bumps the SDK version in go.mod, emits + # .github/workflows/tagging.yml + tagging.py (+ lock) in the repo root, plus + # a next-changelog workflow we don't keep. The cmds below then post-process + # that output: SDK/OpenAPI consistency check, drop the next-changelog + # workflow, relocate tagging.py under internal/genkit/ and rewrite the + # tagging.yml workflow to match, then yamlfmt + whitespace fix so the tree + # is clean. + generate:genkit: + desc: Run genkit to generate CLI commands and tagging workflow (requires universe repo) sources: - .codegen/_openapi_sha - .gitattributes.manual - - tools/post-generate.sh vars: UNIVERSE_DIR: sh: echo "${UNIVERSE_DIR:-$HOME/universe}" @@ -545,6 +548,18 @@ tasks: - echo "Generating CLI code..." - "{{.UNIVERSE_DIR}}/bazel-bin/openapi/genkit/genkit_/genkit update-sdk" - "cat .gitattributes.manual .gitattributes > .gitattributes.tmp && mv .gitattributes.tmp .gitattributes" + - go test -timeout 240s -run TestConsistentDatabricksSdkVersion github.com/databricks/cli/internal/build + - rm .github/workflows/next-changelog.yml + - mv tagging.py internal/genkit/tagging.py + - mv tagging.py.lock internal/genkit/tagging.py.lock + - | + if [ "$(uname)" = "Darwin" ]; then + sed -i '' 's|tagging.py|internal/genkit/tagging.py|g' .github/workflows/tagging.yml + else + sed -i 's|tagging.py|internal/genkit/tagging.py|g' .github/workflows/tagging.yml + fi + - "{{.GO_TOOL}} yamlfmt .github/workflows/tagging.yml" + - ./tools/validate_whitespace.py --fix # Refreshes out.fields.txt, which records the field paths / types emitted by # `bundle debug refschema` (see cmd/bundle/debug/refschema.go). It reflects @@ -676,11 +691,6 @@ tasks: acceptance/bundle/refschema/out.fields.txt > bundle/direct/dresources/resources.generated.yml - generate:direct:clean: - desc: Remove generated direct engine files - cmds: - - rm -f bundle/direct/dresources/apitypes.generated.yml bundle/direct/dresources/resources.generated.yml - generate:openapi-json: desc: Download OpenAPI spec (triggered by _openapi_sha change) sources: diff --git a/tools/post-generate.sh b/tools/post-generate.sh deleted file mode 100755 index 065d110b9b..0000000000 --- a/tools/post-generate.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/bash - -set -euxo pipefail - -# This script runs inside `task generate:commands` via .codegen.json's -# `toolchain.post_generate`. It post-processes files that genkit just wrote -# (generated commands in cmd/, tagging.py, tagging.yml). Generators that read -# bundle config (schema, schema-for-docs, validation, docs) and Python codegen -# live as separate Taskfile tasks and run from the `generate` aggregator — go.mod -# being in their sources invalidates their caches when genkit bumps the SDK. - -# Ensure the SDK version is consistent with the OpenAPI SHA the CLI is generated from. -go test -timeout 240s -run TestConsistentDatabricksSdkVersion github.com/databricks/cli/internal/build - -# Remove the next-changelog.yml workflow. -rm .github/workflows/next-changelog.yml - -# Move the tagging.py file and its lock file to internal/genkit/. We do this to -# avoid cluttering the root directory. The lock file must stay next to tagging.py -# for `uv run --locked` to work in the tagging workflow. -mv tagging.py internal/genkit/tagging.py -mv tagging.py.lock internal/genkit/tagging.py.lock - -# Update the tagging.yml workflow to use the new tagging.py file location. -# The genkit generates "uv run --locked tagging.py", we need to rewrite it -# to point at the moved location. -if [[ "$(uname)" == "Darwin" ]]; then - # macOS (BSD sed) requires empty string after -i - sed -i '' 's|tagging.py|internal/genkit/tagging.py|g' .github/workflows/tagging.yml -else - # Linux (GNU sed) - sed -i 's|tagging.py|internal/genkit/tagging.py|g' .github/workflows/tagging.yml -fi -go tool -modfile=tools/go.mod yamlfmt .github/workflows/tagging.yml - -# Fix whitespace issues in the generated code. -./tools/validate_whitespace.py --fix From 39667a6db619433a85a06330363e75b6a95c82ae Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Mon, 20 Apr 2026 18:29:31 +0200 Subject: [PATCH 24/45] Taskfile: rename python:* tasks to pydabs:* The tasks target the python/databricks-bundles package (pydabs), not Python tooling in general (fmt:python stays, since that one does apply repo-wide). Renaming avoids confusion and matches how the project refers to the package elsewhere. Co-authored-by: Isaac --- .agent/rules/auto-generated-files.md | 2 +- .agent/skills/pr-checklist/SKILL.md | 2 +- .github/workflows/push.yml | 4 ++-- .github/workflows/python_push.yml | 6 ++--- Taskfile.yml | 34 ++++++++++++++-------------- 5 files changed, 24 insertions(+), 24 deletions(-) diff --git a/.agent/rules/auto-generated-files.md b/.agent/rules/auto-generated-files.md index 1ac4450a45..7249ea9f3a 100644 --- a/.agent/rules/auto-generated-files.md +++ b/.agent/rules/auto-generated-files.md @@ -81,7 +81,7 @@ If a change is needed in any matched file: - Mock files: - `go run github.com/vektra/mockery/v2@b9df18e0f7b94f0bc11af3f379c8a9aea1e1e8da` - Python bundle codegen: - - `task python:codegen` + - `task pydabs:codegen` ### Acceptance and test generated outputs diff --git a/.agent/skills/pr-checklist/SKILL.md b/.agent/skills/pr-checklist/SKILL.md index 65b82627b5..e27063760d 100644 --- a/.agent/skills/pr-checklist/SKILL.md +++ b/.agent/skills/pr-checklist/SKILL.md @@ -20,7 +20,7 @@ Before submitting a PR, run these commands to match what CI checks. CI uses the ./task generate:schema # 5. If you changed files in python/: -./task python:codegen python:test python:lint python:docs +./task pydabs:codegen pydabs:test pydabs:lint pydabs:docs # 6. If you changed experimental/aitools or experimental/ssh: ./task test:exp-aitools # only if aitools code changed diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index d0d237fb1f..cc36616d0d 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -372,10 +372,10 @@ jobs: - name: Verify that python/codegen is up to date run: |- - ./task python:codegen + ./task pydabs:codegen if ! ( git diff --exit-code ); then - echo "Generated Python code is not up-to-date. Please run 'task python:codegen' and commit the changes." + echo "Generated Python code is not up-to-date. Please run 'task pydabs:codegen' and commit the changes." exit 1 fi diff --git a/.github/workflows/python_push.yml b/.github/workflows/python_push.yml index b26451aec3..717659985e 100644 --- a/.github/workflows/python_push.yml +++ b/.github/workflows/python_push.yml @@ -44,7 +44,7 @@ jobs: version: "0.6.5" - name: Run tests - run: ./task python:test + run: ./task pydabs:test python_linters: name: lint @@ -65,7 +65,7 @@ jobs: version: "0.6.5" - name: Run lint - run: ./task python:lint + run: ./task pydabs:lint python_docs: name: docs @@ -86,4 +86,4 @@ jobs: version: "0.6.5" - name: Run docs - run: ./task python:docs + run: ./task pydabs:docs diff --git a/Taskfile.yml b/Taskfile.yml index 5f35ee5352..11e7c7fb3a 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -30,9 +30,9 @@ tasks: - task: generate:validation - task: generate:docs - task: generate:direct - - task: python:codegen - - task: python:lint - - task: python:test + - task: pydabs:codegen + - task: pydabs:lint + - task: pydabs:test # --- Linting --- # @@ -518,7 +518,7 @@ tasks: - task: generate:validation - task: generate:docs - task: generate:direct - - task: python:codegen + - task: pydabs:codegen # Drives genkit from a universe checkout. Genkit writes CLI command files into # cmd/workspace and cmd/account, bumps the SDK version in go.mod, emits @@ -700,18 +700,18 @@ tasks: cmds: - "wget -O .codegen/openapi.json.tmp \"https://openapi.dev.databricks.com/$(cat .codegen/_openapi_sha)/specs/all-internal.json\" && mv .codegen/openapi.json.tmp .codegen/openapi.json" - # --- Python --- + # --- pydabs (python/databricks-bundles package) --- - python:test: - desc: Run Python tests + pydabs:test: + desc: Run pydabs tests dir: python sources: - "**/*.py" cmds: - uv run python -m pytest databricks_tests --cov=databricks.bundles --cov-report html -vv - python:lint: - desc: Run Python lint checks + pydabs:lint: + desc: Run pydabs lint checks dir: python sources: - "**/*.py" @@ -723,8 +723,8 @@ tasks: - uv run pyright - uv run ruff format --diff databricks databricks_tests - python:fmt: - desc: Format Python code + pydabs:fmt: + desc: Format pydabs code dir: python sources: - "**/*.py" @@ -732,8 +732,8 @@ tasks: - uv run ruff check --fix databricks databricks_tests || true - uv run ruff format - python:docs: - desc: Generate Python documentation + pydabs:docs: + desc: Generate pydabs documentation dir: python sources: - "**/*.py" @@ -743,8 +743,8 @@ tasks: cmds: - uv run --python 3.12 sphinx-build docs docs/_output --show-traceback --nitpicky --fresh-env --keep-going - python:codegen: - desc: Run Python codegen + pydabs:codegen: + desc: Run pydabs codegen dir: python sources: - codegen/** @@ -763,8 +763,8 @@ tasks: - uv run ruff check --fix databricks databricks_tests || true - uv run ruff format - python:build: - desc: Build Python wheel + pydabs:build: + desc: Build pydabs wheel dir: python cmds: - rm -rf build dist From c8432302c46db75f0c05fcbe2113f759e24c12fc Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Mon, 20 Apr 2026 19:17:30 +0200 Subject: [PATCH 25/45] Taskfile: split test:unit per Go module (root, tools, codegen) The old `test:unit` only ran `go test ./...` in the root module; tests in tools/ and bundle/internal/tf/codegen weren't run. Split into per-module tasks plus an aggregator that concatenates their JSON outputs. Also makes tools/testmask tolerate non-string `sources:` entries (e.g. `- exclude: tools/**`), which previously made yaml.Unmarshal fail once those excludes were introduced. Co-authored-by: Isaac --- .gitignore | 3 ++ Taskfile.yml | 60 ++++++++++++++++++++++++++++++++------- tools/testmask/targets.go | 11 +++++-- 3 files changed, 62 insertions(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index 179a4d18fc..5516d1a40b 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,9 @@ __pycache__ # Test results from 'task test' test-output.json test-output-unit.json +test-output-unit-root.json +test-output-unit-tools.json +test-output-unit-codegen.json test-output-acc.json # Taskfile cache diff --git a/Taskfile.yml b/Taskfile.yml index 11e7c7fb3a..c5f9c3a187 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -299,8 +299,6 @@ tasks: desc: Run unit and acceptance tests (in parallel) deps: - task: test:unit - vars: - TEST_PACKAGES: "{{.TEST_PACKAGES}}" - task: test:acc vars: ACCEPTANCE_TEST_FILTER: "{{.ACCEPTANCE_TEST_FILTER}}" @@ -308,19 +306,61 @@ tasks: - cat test-output-unit.json test-output-acc.json > test-output.json test:unit: - desc: Run unit tests + desc: Run unit tests across all Go modules (root, tools, codegen) + deps: ['test:unit:root', 'test:unit:tools', 'test:unit:codegen'] + cmds: + - cat test-output-unit-root.json test-output-unit-tools.json test-output-unit-codegen.json > test-output-unit.json + + test:unit:root: + desc: Run unit tests in root module sources: - "**/*.go" + - exclude: tools/** + - exclude: bundle/internal/tf/codegen/** cmds: - | {{.GO_TOOL}} gotestsum \ --format ${GOTESTSUM_FORMAT:-pkgname-and-test-fails} \ --no-summary=skipped \ - --jsonfile test-output-unit.json \ + --jsonfile test-output-unit-root.json \ --rerun-fails \ --packages "{{.TEST_PACKAGES}}" \ -- -timeout=${LOCAL_TIMEOUT:-30m} + test:unit:tools: + desc: Run unit tests in tools/ module + dir: tools + sources: + - "**/*.go" + - go.mod + - go.sum + cmds: + - | + {{.GO_TOOL}} gotestsum \ + --format ${GOTESTSUM_FORMAT:-pkgname-and-test-fails} \ + --no-summary=skipped \ + --jsonfile {{.ROOT_DIR}}/test-output-unit-tools.json \ + --rerun-fails \ + --packages ./... \ + -- -timeout=${LOCAL_TIMEOUT:-30m} + + test:unit:codegen: + desc: Run unit tests in bundle/internal/tf/codegen module + dir: bundle/internal/tf/codegen + sources: + - "**/*.go" + - go.mod + - go.sum + cmds: + - | + {{.GO_TOOL}} gotestsum \ + --format ${GOTESTSUM_FORMAT:-pkgname-and-test-fails} \ + --no-summary=skipped \ + --jsonfile {{.ROOT_DIR}}/test-output-unit-codegen.json \ + --rerun-fails \ + --packages ./... \ + -- -timeout=${LOCAL_TIMEOUT:-30m} + test:acc: desc: Run acceptance tests sources: @@ -417,14 +457,14 @@ tasks: - experimental/aitools/** - acceptance/apps/** deps: - - task: test:unit + - task: test:unit:root vars: TEST_PACKAGES: ./experimental/aitools/... - task: test:acc vars: ACCEPTANCE_TEST_FILTER: TestAccept/apps cmds: - - cat test-output-unit.json test-output-acc.json > test-output.json + - cat test-output-unit-root.json test-output-acc.json > test-output.json test:exp-ssh: desc: Run experimental SSH unit and acceptance tests (in parallel) @@ -432,14 +472,14 @@ tasks: - experimental/ssh/** - acceptance/ssh/** deps: - - task: test:unit + - task: test:unit:root vars: TEST_PACKAGES: ./experimental/ssh/... - task: test:acc vars: ACCEPTANCE_TEST_FILTER: TestAccept/ssh cmds: - - cat test-output-unit.json test-output-acc.json > test-output.json + - cat test-output-unit-root.json test-output-acc.json > test-output.json test:pipelines: desc: Run pipelines unit and acceptance tests (in parallel) @@ -447,14 +487,14 @@ tasks: - cmd/pipelines/** - acceptance/pipelines/** deps: - - task: test:unit + - task: test:unit:root vars: TEST_PACKAGES: ./cmd/pipelines/... - task: test:acc vars: ACCEPTANCE_TEST_FILTER: TestAccept/pipelines cmds: - - cat test-output-unit.json test-output-acc.json > test-output.json + - cat test-output-unit-root.json test-output-acc.json > test-output.json # --- Integration tests --- diff --git a/tools/testmask/targets.go b/tools/testmask/targets.go index 1e49192e3c..2901a56b2a 100644 --- a/tools/testmask/targets.go +++ b/tools/testmask/targets.go @@ -34,8 +34,11 @@ type taskfile struct { Tasks map[string]taskfileTask `yaml:"tasks"` } +// Sources uses []any to tolerate non-string entries (e.g. `- exclude: tools/**`) +// that appear on other tasks in Taskfile.yml. We only care about string globs; +// map entries are skipped in LoadTargetMappings. type taskfileTask struct { - Sources []string `yaml:"sources"` + Sources []any `yaml:"sources"` } // LoadTargetMappings reads Taskfile.yml and builds target mappings for CI tasks @@ -64,7 +67,11 @@ func LoadTargetMappings(taskfilePath string) ([]targetMapping, error) { } prefixes := slices.Clone(commonTriggerPatterns) for _, src := range t.Sources { - prefixes = append(prefixes, sourceToPrefix(src)) + s, ok := src.(string) + if !ok { + continue + } + prefixes = append(prefixes, sourceToPrefix(s)) } mappings = append(mappings, targetMapping{prefixes: prefixes, target: outputName}) } From ae1f726e058df3d3a41d1b57ab6a00c7c20575ce Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Mon, 20 Apr 2026 19:17:49 +0200 Subject: [PATCH 26/45] Taskfile: cache test/test:unit merge via sources+generates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously `cat … > test-output-unit.json` (and the top-level `test` merge) ran every invocation even when all sub-tasks were cache-hit. Declaring the inputs as `sources:` and the merged file as `generates:` lets Task skip the cat when nothing upstream changed. Co-authored-by: Isaac --- Taskfile.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Taskfile.yml b/Taskfile.yml index c5f9c3a187..59d0303ca4 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -302,12 +302,23 @@ tasks: - task: test:acc vars: ACCEPTANCE_TEST_FILTER: "{{.ACCEPTANCE_TEST_FILTER}}" + sources: + - test-output-unit.json + - test-output-acc.json + generates: + - test-output.json cmds: - cat test-output-unit.json test-output-acc.json > test-output.json test:unit: desc: Run unit tests across all Go modules (root, tools, codegen) deps: ['test:unit:root', 'test:unit:tools', 'test:unit:codegen'] + sources: + - test-output-unit-root.json + - test-output-unit-tools.json + - test-output-unit-codegen.json + generates: + - test-output-unit.json cmds: - cat test-output-unit-root.json test-output-unit-tools.json test-output-unit-codegen.json > test-output-unit.json From 3e96e296b698932c362b9aacc21799add9d669f3 Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Mon, 20 Apr 2026 19:19:34 +0200 Subject: [PATCH 27/45] Taskfile: rename test:exp-aitools/ssh to test:exp:aitools/ssh MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Consistent with other colon-namespaced tasks (test:unit:*, test:acc). testmask now derives the Taskfile task name from the CI output name by replacing "-" with ":", so the list of targets no longer needs both forms — a single slice suffices. CI target identifiers (job names, cache keys) remain dash-separated. Co-authored-by: Isaac --- .agent/skills/pr-checklist/SKILL.md | 4 ++-- .github/workflows/push.yml | 8 ++++---- Taskfile.yml | 22 +++++++++++----------- tools/testmask/targets.go | 19 ++++++++++--------- 4 files changed, 27 insertions(+), 26 deletions(-) diff --git a/.agent/skills/pr-checklist/SKILL.md b/.agent/skills/pr-checklist/SKILL.md index e27063760d..e2c53ab059 100644 --- a/.agent/skills/pr-checklist/SKILL.md +++ b/.agent/skills/pr-checklist/SKILL.md @@ -23,6 +23,6 @@ Before submitting a PR, run these commands to match what CI checks. CI uses the ./task pydabs:codegen pydabs:test pydabs:lint pydabs:docs # 6. If you changed experimental/aitools or experimental/ssh: -./task test:exp-aitools # only if aitools code changed -./task test:exp-ssh # only if ssh code changed +./task test:exp:aitools # only if aitools code changed +./task test:exp:ssh # only if ssh code changed ``` diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index cc36616d0d..5da00fc759 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -164,7 +164,7 @@ jobs: # Only run if the target is in the list of targets from testmask if: ${{ contains(fromJSON(needs.testmask.outputs.targets), 'test-exp-aitools') }} - name: "task test:exp-aitools (${{matrix.os.name}})" + name: "task test:exp:aitools (${{matrix.os.name}})" runs-on: ${{ matrix.os.runner }} permissions: @@ -201,7 +201,7 @@ jobs: - name: Run tests run: | - ./task test:exp-aitools + ./task test:exp:aitools test-exp-ssh: needs: @@ -210,7 +210,7 @@ jobs: # Only run if the target is in the list of targets from testmask if: ${{ contains(fromJSON(needs.testmask.outputs.targets), 'test-exp-ssh') }} - name: "task test:exp-ssh (${{matrix.os.name}})" + name: "task test:exp:ssh (${{matrix.os.name}})" runs-on: ${{ matrix.os.runner }} permissions: @@ -246,7 +246,7 @@ jobs: - name: Run tests run: | - ./task test:exp-ssh + ./task test:exp:ssh test-pipelines: needs: diff --git a/Taskfile.yml b/Taskfile.yml index 59d0303ca4..24cfbac0b1 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -13,15 +13,11 @@ tasks: - task: checks - task: fmt-q - task: lint-q - - task: test + - task: test-update all: desc: Run all checks, full fmt, full lint, tests, and regeneration cmds: - - task: checks - - task: fmt - - task: lint - - task: test # Skips generate:genkit (expensive, requires universe checkout, outputs are # committed). Run `./task generate` explicitly when codegen inputs change. - task: generate:refschema @@ -33,6 +29,10 @@ tasks: - task: pydabs:codegen - task: pydabs:lint - task: pydabs:test + - task: checks + - task: fmt + - task: lint + - task: test-update-all # --- Linting --- # @@ -387,22 +387,22 @@ tasks: --packages ./acceptance/... \ -- -timeout=${LOCAL_TIMEOUT:-30m}{{if .ACCEPTANCE_TEST_FILTER}} -run "{{.ACCEPTANCE_TEST_FILTER}}"{{end}} - test:update: + test-update: desc: Update acceptance test output (local) cmds: - "-go test ./acceptance -run '^TestAccept$' -update -timeout=${LOCAL_TIMEOUT:-30m}" - test:update-templates: + test-update-templates: desc: Update acceptance test template output cmds: - "-go test ./acceptance -run '^TestAccept/bundle/templates' -update -timeout=${LOCAL_TIMEOUT:-30m}" - test:update-aws: + test-update-aws: desc: Update acceptance test output (integration, requires deco access) cmds: - "deco env run -i -n aws-prod-ucws -- env DATABRICKS_TEST_SKIPLOCAL=1 go test ./acceptance -run ^TestAccept$ -update -timeout=1h -v" - test:update-all: + test-update-all: desc: Update all acceptance test outputs # Sequential: both tasks overwrite the same acceptance output files. cmds: @@ -462,7 +462,7 @@ tasks: # Keep patterns narrow and specific. Changes to files outside these paths trigger the # generic `test` target (the catch-all) instead. - test:exp-aitools: + test:exp:aitools: desc: Run experimental aitools unit and acceptance tests (in parallel) sources: - experimental/aitools/** @@ -477,7 +477,7 @@ tasks: cmds: - cat test-output-unit-root.json test-output-acc.json > test-output.json - test:exp-ssh: + test:exp:ssh: desc: Run experimental SSH unit and acceptance tests (in parallel) sources: - experimental/ssh/** diff --git a/tools/testmask/targets.go b/tools/testmask/targets.go index 2901a56b2a..d01b1d4c7a 100644 --- a/tools/testmask/targets.go +++ b/tools/testmask/targets.go @@ -10,12 +10,13 @@ import ( "gopkg.in/yaml.v3" ) -// ciTargetTasks maps the dash-separated output name used by CI to the -// colon-separated Taskfile task name whose `sources:` define its trigger set. -var ciTargetTasks = map[string]string{ - "test-exp-aitools": "test:exp-aitools", - "test-exp-ssh": "test:exp-ssh", - "test-pipelines": "test:pipelines", +// ciTargets lists the dash-separated CI output names whose trigger sets +// come from the corresponding Taskfile task's `sources:`. The task name is +// derived by replacing "-" with ":" (e.g. "test-exp-ssh" → "test:exp:ssh"). +var ciTargets = []string{ + "test-exp-aitools", + "test-exp-ssh", + "test-pipelines", } // commonTriggerPatterns lists patterns that trigger all test targets. @@ -42,7 +43,7 @@ type taskfileTask struct { } // LoadTargetMappings reads Taskfile.yml and builds target mappings for CI tasks -// by extracting `sources:` from each task listed in ciTargetTasks. +// by extracting `sources:` from each task listed in ciTargets. func LoadTargetMappings(taskfilePath string) ([]targetMapping, error) { data, err := os.ReadFile(taskfilePath) if err != nil { @@ -56,8 +57,8 @@ func LoadTargetMappings(taskfilePath string) ([]targetMapping, error) { mappings := []targetMapping{ {prefixes: slices.Clone(commonTriggerPatterns), target: "test"}, } - for _, outputName := range slices.Sorted(maps.Keys(ciTargetTasks)) { - taskName := ciTargetTasks[outputName] + for _, outputName := range ciTargets { + taskName := strings.ReplaceAll(outputName, "-", ":") t, ok := tf.Tasks[taskName] if !ok { return nil, fmt.Errorf("task %q not found in %s", taskName, taskfilePath) From a9d88d25c54a7b1489c5dca355458a371f44b2e0 Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Mon, 20 Apr 2026 19:23:55 +0200 Subject: [PATCH 28/45] Taskfile: flatten integration:short, dbr:integration, dbr:test Rename to integration-short, dbr-integration, dbr-test. These are single-task variants without a parent aggregator, so dash suffixes fit better than colon namespacing. Co-authored-by: Isaac --- Taskfile.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Taskfile.yml b/Taskfile.yml index 24cfbac0b1..447d145b39 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -522,7 +522,7 @@ tasks: --packages "./acceptance ./integration/..." \ -- -parallel 4 -timeout=2h - integration:short: + integration-short: desc: Run short integration tests deps: [install-pythons] cmds: @@ -536,16 +536,16 @@ tasks: --packages "./acceptance ./integration/..." \ -- -parallel 4 -timeout=2h -short - dbr:integration: + dbr-integration: desc: Run DBR acceptance tests on Databricks Runtime deps: [install-pythons] cmds: - "DBR_ENABLED=true go test -v -timeout 4h -run TestDbrAcceptance$ ./acceptance" - dbr:test: + dbr-test: desc: Run DBR tests via deco env (requires deco + aws-prod-ucws access) cmds: - - "deco env run -i -n aws-prod-ucws -- ./task dbr:integration" + - "deco env run -i -n aws-prod-ucws -- ./task dbr-integration" # --- Code generation --- # From 264202525465506f481ee28bc81dbe9bb8dfee1e Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Mon, 20 Apr 2026 19:24:39 +0200 Subject: [PATCH 29/45] Taskfile: drop "(in parallel)" from test task descriptions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Redundant — the `deps:` structure already makes parallel execution obvious to anyone reading the task definition, and users running `./task --list` don't need that implementation detail in the summary. Co-authored-by: Isaac --- Taskfile.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Taskfile.yml b/Taskfile.yml index 447d145b39..fa514d5232 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -296,7 +296,7 @@ tasks: # --- Testing --- test: - desc: Run unit and acceptance tests (in parallel) + desc: Run unit and acceptance tests deps: - task: test:unit - task: test:acc @@ -463,7 +463,7 @@ tasks: # generic `test` target (the catch-all) instead. test:exp:aitools: - desc: Run experimental aitools unit and acceptance tests (in parallel) + desc: Run experimental aitools unit and acceptance tests sources: - experimental/aitools/** - acceptance/apps/** @@ -478,7 +478,7 @@ tasks: - cat test-output-unit-root.json test-output-acc.json > test-output.json test:exp:ssh: - desc: Run experimental SSH unit and acceptance tests (in parallel) + desc: Run experimental SSH unit and acceptance tests sources: - experimental/ssh/** - acceptance/ssh/** @@ -493,7 +493,7 @@ tasks: - cat test-output-unit-root.json test-output-acc.json > test-output.json test:pipelines: - desc: Run pipelines unit and acceptance tests (in parallel) + desc: Run pipelines unit and acceptance tests sources: - cmd/pipelines/** - acceptance/pipelines/** From 564ecdaaba39174219043653c0d8e1419923774f Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Mon, 20 Apr 2026 19:26:13 +0200 Subject: [PATCH 30/45] =?UTF-8?q?Taskfile:=20fix=20generate:genkit=20comme?= =?UTF-8?q?nts=20=E2=80=94=20genkit=20does=20not=20bump=20go.mod?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previous comments claimed generate:genkit bumps the SDK version in go.mod/go.sum; it doesn't. Genkit regenerates CLI command stubs from .codegen/_openapi_sha and refreshes .gitattributes, but SDK bumps are a manual `go get` step. TestConsistentDatabricksSdkVersion is what keeps the two in sync. Co-authored-by: Isaac --- Taskfile.yml | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/Taskfile.yml b/Taskfile.yml index fa514d5232..6625a7db2c 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -558,8 +558,10 @@ tasks: generate: desc: Run all generators (genkit, refschema, schema, docs, validation, direct, pydabs) cmds: - # Runs first: may bump go.mod (SDK version), which invalidates reflection- - # based generators below so they re-run automatically. + # Runs first: regenerates CLI command stubs from the OpenAPI spec at + # .codegen/_openapi_sha. SDK version bumps (go.mod/go.sum) are a manual + # step outside this task; TestConsistentDatabricksSdkVersion (run inside + # generate:genkit) asserts the two stay in sync. - task: generate:genkit # Refreshes acceptance/bundle/refschema/out.fields.txt, which feeds # generate:direct:apitypes and generate:direct:resources below. @@ -572,13 +574,15 @@ tasks: - task: pydabs:codegen # Drives genkit from a universe checkout. Genkit writes CLI command files into - # cmd/workspace and cmd/account, bumps the SDK version in go.mod, emits - # .github/workflows/tagging.yml + tagging.py (+ lock) in the repo root, plus - # a next-changelog workflow we don't keep. The cmds below then post-process - # that output: SDK/OpenAPI consistency check, drop the next-changelog - # workflow, relocate tagging.py under internal/genkit/ and rewrite the - # tagging.yml workflow to match, then yamlfmt + whitespace fix so the tree - # is clean. + # cmd/workspace and cmd/account, refreshes .gitattributes and + # .codegen/_openapi_sha, and emits .github/workflows/tagging.yml + + # tagging.py (+ lock) in the repo root plus a next-changelog workflow we + # don't keep. Genkit does NOT modify go.mod/go.sum — SDK bumps are a manual + # `go get` step before running this task. The cmds below then post-process + # genkit's output: assert the SDK version matches the OpenAPI SHA, drop the + # next-changelog workflow, relocate tagging.py under internal/genkit/ and + # rewrite the tagging.yml workflow to match, then yamlfmt + whitespace fix + # so the tree is clean. generate:genkit: desc: Run genkit to generate CLI commands and tagging workflow (requires universe repo) sources: From 1f935a5cc2df7f41465afc8971748255049d255d Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Tue, 21 Apr 2026 12:38:39 +0200 Subject: [PATCH 31/45] Taskfile: use dash separators for all task names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace every `:` with `-` in task names, so every task is a valid target name for tools that don't allow `:` — primarily `make`, where `make test:unit` parses as target `test` with prerequisite `unit` rather than as a single target `test:unit`. With dashes everywhere: * `make X` and `./task X` invoke the same task for every X, making the Makefile wrapper a true drop-in for former `make` users. * testmask no longer needs the CI-name ↔ Taskfile-name translation: the CI job output names are the task names. CI job identifiers (job names, cache-key strings) are unchanged; they were already dash-separated. Co-authored-by: Isaac --- .agent/rules/auto-generated-files.md | 14 +- .agent/skills/pr-checklist/SKILL.md | 8 +- .github/workflows/push.yml | 26 ++-- .github/workflows/python_push.yml | 6 +- AGENTS.md | 8 +- Taskfile.yml | 194 +++++++++++++-------------- bundle/docsgen/README.md | 8 +- bundle/internal/schema/main_test.go | 4 +- tools/testmask/targets.go | 16 +-- 9 files changed, 141 insertions(+), 143 deletions(-) diff --git a/.agent/rules/auto-generated-files.md b/.agent/rules/auto-generated-files.md index 7249ea9f3a..7140e2fb3c 100644 --- a/.agent/rules/auto-generated-files.md +++ b/.agent/rules/auto-generated-files.md @@ -66,22 +66,22 @@ If a change is needed in any matched file: - Everything, in one shot: - `task generate` — aggregator that runs all generators below - OpenAPI SDK/CLI command stubs and related generated artifacts: - - `task generate:genkit` + - `task generate-genkit` - Includes generated `cmd/account/**`, `cmd/workspace/**`, `.gitattributes`, `internal/genkit/tagging.py`. - Direct engine generated YAML: - - `task generate:direct` (or `task generate:direct:apitypes`, `task generate:direct:resources`) + - `task generate-direct` (or `task generate-direct-apitypes`, `task generate-direct-resources`) - Bundle schemas: - - `task generate:schema` - - `task generate:schema-docs` + - `task generate-schema` + - `task generate-schema-docs` - This can also refresh `bundle/internal/schema/annotations_openapi.yml` when OpenAPI annotation extraction is enabled. - Bundle docs: - - `task generate:docs` + - `task generate-docs` - Validation generated code: - - `task generate:validation` + - `task generate-validation` - Mock files: - `go run github.com/vektra/mockery/v2@b9df18e0f7b94f0bc11af3f379c8a9aea1e1e8da` - Python bundle codegen: - - `task pydabs:codegen` + - `task pydabs-codegen` ### Acceptance and test generated outputs diff --git a/.agent/skills/pr-checklist/SKILL.md b/.agent/skills/pr-checklist/SKILL.md index e2c53ab059..a8d93af29f 100644 --- a/.agent/skills/pr-checklist/SKILL.md +++ b/.agent/skills/pr-checklist/SKILL.md @@ -17,12 +17,12 @@ Before submitting a PR, run these commands to match what CI checks. CI uses the ./task test # 4. If you changed bundle config structs or schema-related code: -./task generate:schema +./task generate-schema # 5. If you changed files in python/: -./task pydabs:codegen pydabs:test pydabs:lint pydabs:docs +./task pydabs-codegen pydabs-test pydabs-lint pydabs-docs # 6. If you changed experimental/aitools or experimental/ssh: -./task test:exp:aitools # only if aitools code changed -./task test:exp:ssh # only if ssh code changed +./task test-exp-aitools # only if aitools code changed +./task test-exp-ssh # only if ssh code changed ``` diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 5da00fc759..47c0c9388b 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -153,7 +153,7 @@ jobs: shell: bash run: | if ! git diff --exit-code; then - echo "ERROR: detected changed files in the repository; Most likely you have out.test.toml files that are out of date. Run './task generate:out-test-toml' to update." + echo "ERROR: detected changed files in the repository; Most likely you have out.test.toml files that are out of date. Run './task generate-out-test-toml' to update." exit 1 fi @@ -164,7 +164,7 @@ jobs: # Only run if the target is in the list of targets from testmask if: ${{ contains(fromJSON(needs.testmask.outputs.targets), 'test-exp-aitools') }} - name: "task test:exp:aitools (${{matrix.os.name}})" + name: "task test-exp-aitools (${{matrix.os.name}})" runs-on: ${{ matrix.os.runner }} permissions: @@ -201,7 +201,7 @@ jobs: - name: Run tests run: | - ./task test:exp:aitools + ./task test-exp-aitools test-exp-ssh: needs: @@ -210,7 +210,7 @@ jobs: # Only run if the target is in the list of targets from testmask if: ${{ contains(fromJSON(needs.testmask.outputs.targets), 'test-exp-ssh') }} - name: "task test:exp:ssh (${{matrix.os.name}})" + name: "task test-exp-ssh (${{matrix.os.name}})" runs-on: ${{ matrix.os.runner }} permissions: @@ -246,7 +246,7 @@ jobs: - name: Run tests run: | - ./task test:exp:ssh + ./task test-exp-ssh test-pipelines: needs: @@ -255,7 +255,7 @@ jobs: # Only run if the target is in the list of targets from testmask if: ${{ contains(fromJSON(needs.testmask.outputs.targets), 'test-pipelines') }} - name: "task test:pipelines (${{matrix.os.name}})" + name: "task test-pipelines (${{matrix.os.name}})" runs-on: ${{ matrix.os.runner }} permissions: @@ -291,7 +291,7 @@ jobs: - name: Run tests run: | - ./task test:pipelines + ./task test-pipelines # This job groups the result of all the above test jobs. # It is a required check, so it blocks auto-merge and the merge queue. @@ -340,15 +340,15 @@ jobs: - name: Verify that the schema is up to date run: | - if ! ( ./task --force generate:schema && git diff --exit-code ); then - echo "The schema is not up to date. Please run 'task generate:schema' and commit the changes." + if ! ( ./task --force generate-schema && git diff --exit-code ); then + echo "The schema is not up to date. Please run 'task generate-schema' and commit the changes." exit 1 fi - name: Verify that the generated enum and required fields are up to date run: | - if ! ( ./task --force generate:validation && git diff --exit-code ); then - echo "The generated enum and required fields are not up to date. Please run 'task generate:validation' and commit the changes." + if ! ( ./task --force generate-validation && git diff --exit-code ); then + echo "The generated enum and required fields are not up to date. Please run 'task generate-validation' and commit the changes." exit 1 fi @@ -372,10 +372,10 @@ jobs: - name: Verify that python/codegen is up to date run: |- - ./task pydabs:codegen + ./task pydabs-codegen if ! ( git diff --exit-code ); then - echo "Generated Python code is not up-to-date. Please run 'task pydabs:codegen' and commit the changes." + echo "Generated Python code is not up-to-date. Please run 'task pydabs-codegen' and commit the changes." exit 1 fi diff --git a/.github/workflows/python_push.yml b/.github/workflows/python_push.yml index 717659985e..1ac3cb376e 100644 --- a/.github/workflows/python_push.yml +++ b/.github/workflows/python_push.yml @@ -44,7 +44,7 @@ jobs: version: "0.6.5" - name: Run tests - run: ./task pydabs:test + run: ./task pydabs-test python_linters: name: lint @@ -65,7 +65,7 @@ jobs: version: "0.6.5" - name: Run lint - run: ./task pydabs:lint + run: ./task pydabs-lint python_docs: name: docs @@ -86,4 +86,4 @@ jobs: version: "0.6.5" - name: Run docs - run: ./task pydabs:docs + run: ./task pydabs-docs diff --git a/AGENTS.md b/AGENTS.md index 053d43ae58..74b723a8b1 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -29,9 +29,9 @@ When moving code from one place to another, please don't unnecessarily change th ### Specialized Commands -- `task generate:schema` - Generate bundle JSON schema -- `task generate:docs` - Generate bundle documentation -- `task generate:genkit` - Run genkit to generate CLI commands and tagging workflow (requires universe repo) +- `task generate-schema` - Generate bundle JSON schema +- `task generate-docs` - Generate bundle documentation +- `task generate-genkit` - Run genkit to generate CLI commands and tagging workflow (requires universe repo) - `task generate` - Run all generators ### Git Commands @@ -79,7 +79,7 @@ GIT_EDITOR=true GIT_SEQUENCE_EDITOR=true VISUAL=true GIT_PAGER=cat git rebase or # Development Tips -- Use `task test:update` to regenerate acceptance test outputs after changes +- Use `task test-update` to regenerate acceptance test outputs after changes - The CLI binary supports both `databricks` and `pipelines` command modes based on executable name - Comments should explain "why", not "what" — reviewers consistently reject comments that merely restate the code diff --git a/Taskfile.yml b/Taskfile.yml index 6625a7db2c..8c51e7ff57 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -1,7 +1,7 @@ version: '3' vars: - # Absolute path so tasks with `dir:` (lint:go:tools, lint:go:codegen) can use it. + # Absolute path so tasks with `dir:` (lint-go-tools, lint-go-codegen) can use it. GO_TOOL: go tool -modfile={{.ROOT_DIR}}/tools/go.mod TEST_PACKAGES: ./acceptance/internal ./libs/... ./internal/... ./cmd/... ./bundle/... ./experimental/ssh/... . ACCEPTANCE_TEST_FILTER: "" @@ -18,17 +18,17 @@ tasks: all: desc: Run all checks, full fmt, full lint, tests, and regeneration cmds: - # Skips generate:genkit (expensive, requires universe checkout, outputs are + # Skips generate-genkit (expensive, requires universe checkout, outputs are # committed). Run `./task generate` explicitly when codegen inputs change. - - task: generate:refschema - - task: generate:schema - - task: generate:schema-docs - - task: generate:validation - - task: generate:docs - - task: generate:direct - - task: pydabs:codegen - - task: pydabs:lint - - task: pydabs:test + - task: generate-refschema + - task: generate-schema + - task: generate-schema-docs + - task: generate-validation + - task: generate-docs + - task: generate-direct + - task: pydabs-codegen + - task: pydabs-lint + - task: pydabs-test - task: checks - task: fmt - task: lint @@ -38,34 +38,34 @@ tasks: # # Naming convention: the plain name is the full variant (default). Quick # / incremental variants carry a `-q` suffix on the top-level namespace - # (e.g. `lint-q:go:root`). `./task` (default) uses the -q variants for + # (e.g. `lint-q-go-root`). `./task` (default) uses the -q variants for # speed; `./task all` uses the full variants. lint: desc: Lint all Go files (root + tools + codegen modules) cmds: - - task: lint:go + - task: lint-go lint-q: desc: Lint changed Go files in root module (diff vs main, with --fix) cmds: - - task: lint-q:go:root + - task: lint-q-go-root # `golangci-lint run` typechecks, so it stops at go.mod boundaries. We have - # one task per Go module; `lint:go` composes them to cover the whole repo. + # one task per Go module; `lint-go` composes them to cover the whole repo. # Children run in parallel — each uses its own TMPDIR (set inline on the # golangci-lint command below) to avoid the shared /tmp lock that serializes # concurrent golangci-lint invocations. This matters in two scenarios: - # 1. siblings of `lint:go` running in parallel on subprojects here, and - # 2. `lint:go` invocations in sibling worktrees running at the same time. + # 1. siblings of `lint-go` running in parallel on subprojects here, and + # 2. `lint-go` invocations in sibling worktrees running at the same time. # The TMPDIR must live under the repo but NOT equal {{.ROOT_DIR}} itself # (the Go toolchain refuses a go.mod inside os.TempDir, which would break # golangci-lint's typechecker). - lint:go: + lint-go: desc: Lint Go files across all modules (root, tools, codegen) - deps: ['lint:go:root', 'lint:go:tools', 'lint:go:codegen'] + deps: ['lint-go-root', 'lint-go-tools', 'lint-go-codegen'] - lint:go:root: + lint-go-root: desc: Lint Go files in the root module vars: TMPDIR: '{{.ROOT_DIR}}/.tmp/golangci-lint-root' @@ -79,7 +79,7 @@ tasks: silent: true - TMPDIR="{{.TMPDIR}}" {{.GO_TOOL}} golangci-lint run ./... - lint:go:tools: + lint-go-tools: desc: Lint Go files in tools/ module dir: tools vars: @@ -94,7 +94,7 @@ tasks: silent: true - TMPDIR="{{.TMPDIR}}" {{.GO_TOOL}} golangci-lint run ./... - lint:go:codegen: + lint-go-codegen: desc: Lint Go files in bundle/internal/tf/codegen module dir: bundle/internal/tf/codegen vars: @@ -109,7 +109,7 @@ tasks: silent: true - TMPDIR="{{.TMPDIR}}" {{.GO_TOOL}} golangci-lint run ./... - lint-q:go:root: + lint-q-go-root: desc: Lint changed Go files in root module (diff vs main, with --fix). Does not check tools/ or bundle/internal/tf/codegen — use `lint` for full coverage. vars: TMPDIR: '{{.ROOT_DIR}}/.tmp/golangci-lint-root' @@ -127,13 +127,13 @@ tasks: fmt: desc: Format all files (Python, Go, YAML) - deps: ['fmt:python', 'fmt:go', 'fmt:yaml'] + deps: ['fmt-python', 'fmt-go', 'fmt-yaml'] fmt-q: desc: Format changed files (Python, incremental Go, YAML) - deps: ['fmt:python', 'fmt-q:go', 'fmt:yaml'] + deps: ['fmt-python', 'fmt-q-go', 'fmt-yaml'] - fmt:python: + fmt-python: desc: Format Python files sources: - "**/*.py" @@ -143,7 +143,7 @@ tasks: # `golangci-lint fmt` walks the filesystem and doesn't typecheck, so it # formats files across all nested modules (tools/, bundle/internal/tf/codegen/) # in a single invocation. - fmt:go: + fmt-go: desc: Format all Go files sources: - "**/*.go" @@ -151,7 +151,7 @@ tasks: cmds: - "{{.GO_TOOL}} golangci-lint fmt" - fmt-q:go: + fmt-q-go: desc: Format changed Go files (diff vs main) sources: - "**/*.go" @@ -159,7 +159,7 @@ tasks: cmds: - "./tools/lintdiff.py {{.GO_TOOL}} golangci-lint fmt" - fmt:yaml: + fmt-yaml: desc: Format YAML files sources: - "**/*.yml" @@ -172,9 +172,9 @@ tasks: tidy: desc: Run go mod tidy across all Go modules (root, tools, codegen) - deps: ['tidy:root', 'tidy:tools', 'tidy:codegen'] + deps: ['tidy-root', 'tidy-tools', 'tidy-codegen'] - tidy:root: + tidy-root: desc: Run go mod tidy in root module sources: - go.mod @@ -185,7 +185,7 @@ tasks: cmds: - go mod tidy - tidy:tools: + tidy-tools: desc: Run go mod tidy in tools/ module dir: tools sources: @@ -195,7 +195,7 @@ tasks: cmds: - go mod tidy - tidy:codegen: + tidy-codegen: desc: Run go mod tidy in bundle/internal/tf/codegen module dir: bundle/internal/tf/codegen sources: @@ -210,7 +210,7 @@ tasks: cmds: - ./tools/validate_whitespace.py - ws:fix: + ws-fix: desc: Fix whitespace issues cmds: - ./tools/validate_whitespace.py --fix @@ -243,7 +243,7 @@ tasks: # (tools/, bundle/internal/tf/codegen/), and _test.go files don't affect the build. build: desc: Build the CLI binary - deps: ['tidy:root'] + deps: ['tidy-root'] sources: - "**/*.go" - exclude: "**/*_test.go" @@ -260,7 +260,7 @@ tasks: snapshot: desc: Build snapshot binary to .databricks/databricks - deps: ['tidy:root'] + deps: ['tidy-root'] sources: - "**/*.go" - exclude: "**/*_test.go" @@ -275,9 +275,9 @@ tasks: cmds: - go build -o .databricks/databricks - snapshot:release: + snapshot-release: desc: Build release binaries locally without uploading - deps: ['tidy:root'] + deps: ['tidy-root'] sources: - "**/*.go" - exclude: "**/*_test.go" @@ -298,8 +298,8 @@ tasks: test: desc: Run unit and acceptance tests deps: - - task: test:unit - - task: test:acc + - task: test-unit + - task: test-acc vars: ACCEPTANCE_TEST_FILTER: "{{.ACCEPTANCE_TEST_FILTER}}" sources: @@ -310,9 +310,9 @@ tasks: cmds: - cat test-output-unit.json test-output-acc.json > test-output.json - test:unit: + test-unit: desc: Run unit tests across all Go modules (root, tools, codegen) - deps: ['test:unit:root', 'test:unit:tools', 'test:unit:codegen'] + deps: ['test-unit-root', 'test-unit-tools', 'test-unit-codegen'] sources: - test-output-unit-root.json - test-output-unit-tools.json @@ -322,7 +322,7 @@ tasks: cmds: - cat test-output-unit-root.json test-output-unit-tools.json test-output-unit-codegen.json > test-output-unit.json - test:unit:root: + test-unit-root: desc: Run unit tests in root module sources: - "**/*.go" @@ -338,7 +338,7 @@ tasks: --packages "{{.TEST_PACKAGES}}" \ -- -timeout=${LOCAL_TIMEOUT:-30m} - test:unit:tools: + test-unit-tools: desc: Run unit tests in tools/ module dir: tools sources: @@ -355,7 +355,7 @@ tasks: --packages ./... \ -- -timeout=${LOCAL_TIMEOUT:-30m} - test:unit:codegen: + test-unit-codegen: desc: Run unit tests in bundle/internal/tf/codegen module dir: bundle/internal/tf/codegen sources: @@ -372,7 +372,7 @@ tasks: --packages ./... \ -- -timeout=${LOCAL_TIMEOUT:-30m} - test:acc: + test-acc: desc: Run acceptance tests sources: - "**/*.go" @@ -406,10 +406,10 @@ tasks: desc: Update all acceptance test outputs # Sequential: both tasks overwrite the same acceptance output files. cmds: - - task: test:update - - task: test:update-aws + - task: test-update + - task: test-update-aws - generate:out-test-toml: + generate-out-test-toml: desc: Regenerate out.test.toml files without running tests cmds: - "go test ./acceptance -run '^TestAccept$' -only-out-test-toml -timeout=${LOCAL_TIMEOUT:-30m}" @@ -449,7 +449,7 @@ tasks: cmds: - go tool cover -html=coverage.txt - showcover:acc: + showcover-acc: desc: Open acceptance test coverage report in browser cmds: - go tool cover -html=coverage-acceptance.txt @@ -462,46 +462,46 @@ tasks: # Keep patterns narrow and specific. Changes to files outside these paths trigger the # generic `test` target (the catch-all) instead. - test:exp:aitools: + test-exp-aitools: desc: Run experimental aitools unit and acceptance tests sources: - experimental/aitools/** - acceptance/apps/** deps: - - task: test:unit:root + - task: test-unit-root vars: TEST_PACKAGES: ./experimental/aitools/... - - task: test:acc + - task: test-acc vars: ACCEPTANCE_TEST_FILTER: TestAccept/apps cmds: - cat test-output-unit-root.json test-output-acc.json > test-output.json - test:exp:ssh: + test-exp-ssh: desc: Run experimental SSH unit and acceptance tests sources: - experimental/ssh/** - acceptance/ssh/** deps: - - task: test:unit:root + - task: test-unit-root vars: TEST_PACKAGES: ./experimental/ssh/... - - task: test:acc + - task: test-acc vars: ACCEPTANCE_TEST_FILTER: TestAccept/ssh cmds: - cat test-output-unit-root.json test-output-acc.json > test-output.json - test:pipelines: + test-pipelines: desc: Run pipelines unit and acceptance tests sources: - cmd/pipelines/** - acceptance/pipelines/** deps: - - task: test:unit:root + - task: test-unit-root vars: TEST_PACKAGES: ./cmd/pipelines/... - - task: test:acc + - task: test-acc vars: ACCEPTANCE_TEST_FILTER: TestAccept/pipelines cmds: @@ -561,17 +561,17 @@ tasks: # Runs first: regenerates CLI command stubs from the OpenAPI spec at # .codegen/_openapi_sha. SDK version bumps (go.mod/go.sum) are a manual # step outside this task; TestConsistentDatabricksSdkVersion (run inside - # generate:genkit) asserts the two stay in sync. - - task: generate:genkit + # generate-genkit) asserts the two stay in sync. + - task: generate-genkit # Refreshes acceptance/bundle/refschema/out.fields.txt, which feeds - # generate:direct:apitypes and generate:direct:resources below. - - task: generate:refschema - - task: generate:schema - - task: generate:schema-docs - - task: generate:validation - - task: generate:docs - - task: generate:direct - - task: pydabs:codegen + # generate-direct-apitypes and generate-direct-resources below. + - task: generate-refschema + - task: generate-schema + - task: generate-schema-docs + - task: generate-validation + - task: generate-docs + - task: generate-direct + - task: pydabs-codegen # Drives genkit from a universe checkout. Genkit writes CLI command files into # cmd/workspace and cmd/account, refreshes .gitattributes and @@ -583,7 +583,7 @@ tasks: # next-changelog workflow, relocate tagging.py under internal/genkit/ and # rewrite the tagging.yml workflow to match, then yamlfmt + whitespace fix # so the tree is clean. - generate:genkit: + generate-genkit: desc: Run genkit to generate CLI commands and tagging workflow (requires universe repo) sources: - .codegen/_openapi_sha @@ -620,7 +620,7 @@ tasks: # `bundle debug refschema` (see cmd/bundle/debug/refschema.go). It reflects # over types reachable from bundle/, so any bundle change or SDK bump (go.mod # / go.sum) can affect the output. - generate:refschema: + generate-refschema: desc: Regenerate acceptance/bundle/refschema/out.fields.txt sources: - bundle/**/*.go @@ -634,7 +634,7 @@ tasks: cmds: - go test ./acceptance -run TestAccept/bundle/refschema -update &> /dev/null - generate:schema: + generate-schema: desc: Generate bundle JSON schema sources: - bundle/internal/schema/*.go @@ -651,7 +651,7 @@ tasks: cmds: - go run ./bundle/internal/schema ./bundle/internal/schema ./bundle/schema/jsonschema.json - generate:schema-docs: + generate-schema-docs: desc: Generate bundle JSON schema for documentation sources: - bundle/internal/schema/*.go @@ -668,7 +668,7 @@ tasks: cmds: - go run ./bundle/internal/schema ./bundle/internal/schema ./bundle/schema/jsonschema_for_docs.json --docs - generate:docs: + generate-docs: desc: Generate bundle documentation sources: - bundle/docsgen/*.go @@ -689,7 +689,7 @@ tasks: cmds: - go run ./bundle/docsgen ./bundle/internal/schema ./bundle/docsgen - generate:validation: + generate-validation: desc: Generate enum and required field validation code sources: - bundle/internal/validation/*.go @@ -706,13 +706,13 @@ tasks: - go run ./bundle/internal/validation/. - gofmt -w -s ./bundle/internal/validation/generated - generate:direct: + generate-direct: desc: Generate direct engine config (apitypes + resources) - deps: ['generate:direct:apitypes', 'generate:direct:resources'] + deps: ['generate-direct-apitypes', 'generate-direct-resources'] - generate:direct:apitypes: + generate-direct-apitypes: desc: Generate direct engine API types YAML - deps: ['generate:openapi-json'] + deps: ['generate-openapi-json'] sources: - bundle/direct/tools/generate_apitypes.py - .codegen/openapi.json @@ -726,9 +726,9 @@ tasks: acceptance/bundle/refschema/out.fields.txt > bundle/direct/dresources/apitypes.generated.yml - generate:direct:resources: + generate-direct-resources: desc: Generate direct engine resources YAML - deps: ['generate:direct:apitypes'] + deps: ['generate-direct-apitypes'] sources: - bundle/direct/tools/generate_resources.py - .codegen/openapi.json @@ -746,7 +746,7 @@ tasks: acceptance/bundle/refschema/out.fields.txt > bundle/direct/dresources/resources.generated.yml - generate:openapi-json: + generate-openapi-json: desc: Download OpenAPI spec (triggered by _openapi_sha change) sources: - .codegen/_openapi_sha @@ -757,7 +757,7 @@ tasks: # --- pydabs (python/databricks-bundles package) --- - pydabs:test: + pydabs-test: desc: Run pydabs tests dir: python sources: @@ -765,7 +765,7 @@ tasks: cmds: - uv run python -m pytest databricks_tests --cov=databricks.bundles --cov-report html -vv - pydabs:lint: + pydabs-lint: desc: Run pydabs lint checks dir: python sources: @@ -778,7 +778,7 @@ tasks: - uv run pyright - uv run ruff format --diff databricks databricks_tests - pydabs:fmt: + pydabs-fmt: desc: Format pydabs code dir: python sources: @@ -787,7 +787,7 @@ tasks: - uv run ruff check --fix databricks databricks_tests || true - uv run ruff format - pydabs:docs: + pydabs-docs: desc: Generate pydabs documentation dir: python sources: @@ -798,7 +798,7 @@ tasks: cmds: - uv run --python 3.12 sphinx-build docs docs/_output --show-traceback --nitpicky --fresh-env --keep-going - pydabs:codegen: + pydabs-codegen: desc: Run pydabs codegen dir: python sources: @@ -818,7 +818,7 @@ tasks: - uv run ruff check --fix databricks databricks_tests || true - uv run ruff format - pydabs:build: + pydabs-build: desc: Build pydabs wheel dir: python cmds: @@ -827,35 +827,35 @@ tasks: # --- Benchmarks --- - bench:1k: + bench-1k: desc: Benchmark with 1000 jobs cmds: - 'BENCHMARK_PARAMS="--jobs 1000" go test ./acceptance -v -tail -run TestAccept/bundle/benchmarks -timeout=120m | tee bench1k.log' - bench:100: + bench-100: desc: Benchmark with 100 jobs cmds: - 'BENCHMARK_PARAMS="--jobs 100" go test ./acceptance -v -tail -run TestAccept/bundle/benchmarks -timeout=120m | tee bench100.log' - bench:10: + bench-10: desc: Benchmark with 10 jobs (quick) cmds: - 'BENCHMARK_PARAMS="--jobs 10" go test ./acceptance -v -tail -run TestAccept/bundle/benchmarks -timeout=120m | tee bench10.log' - bench:1k-summary: + bench-1k-summary: desc: Run 1k benchmark and print summary cmds: - - task: bench:1k + - task: bench-1k - ./tools/bench_parse.py bench1k.log - bench:100-summary: + bench-100-summary: desc: Run 100 benchmark and print summary cmds: - - task: bench:100 + - task: bench-100 - ./tools/bench_parse.py bench100.log - bench:10-summary: + bench-10-summary: desc: Run 10 benchmark and print summary cmds: - - task: bench:10 + - task: bench-10 - ./tools/bench_parse.py bench10.log diff --git a/bundle/docsgen/README.md b/bundle/docsgen/README.md index a88e828ad4..5d5517def2 100644 --- a/bundle/docsgen/README.md +++ b/bundle/docsgen/README.md @@ -1,14 +1,14 @@ ## docs-autogen 1. Install [Golang](https://go.dev/doc/install) -2. Run `task generate:docs` from the repo +2. Run `task generate-docs` from the repo 3. See generated documents in `./bundle/docsgen/output` directory -4. To change descriptions update content in `./bundle/internal/schema/annotations.yml` or `./bundle/internal/schema/annotations_openapi_overrides.yml` and re-run `task generate:docs` +4. To change descriptions update content in `./bundle/internal/schema/annotations.yml` or `./bundle/internal/schema/annotations_openapi_overrides.yml` and re-run `task generate-docs` For simpler usage run it together with copy command to move resulting files to local `docs` repo. Note that it will overwrite any local changes in affected files. Example: ``` -task generate:docs && cp bundle/docgen/output/*.md ../docs/source/dev-tools/bundles +task generate-docs && cp bundle/docgen/output/*.md ../docs/source/dev-tools/bundles ``` To change intro sections for files update them in `templates/` directory @@ -76,4 +76,4 @@ github.com/databricks/cli/bundle/config.Bundle: ### TODO -Add file watcher to track changes in the annotation files and re-run `task generate:docs` script automtically +Add file watcher to track changes in the annotation files and re-run `task generate-docs` script automtically diff --git a/bundle/internal/schema/main_test.go b/bundle/internal/schema/main_test.go index fab75b7dbd..d37fa3d155 100644 --- a/bundle/internal/schema/main_test.go +++ b/bundle/internal/schema/main_test.go @@ -43,9 +43,9 @@ func copyFile(src, dst string) error { // Checks whether descriptions are added for new config fields in the annotations.yml file // If this test fails either manually add descriptions to the `annotations.yml` or do the following: // 1. for fields described outside of CLI package fetch latest schema from the OpenAPI spec and add path to file to DATABRICKS_OPENAPI_SPEC env variable -// 2. run `task generate:schema` from the repository root to add placeholder descriptions +// 2. run `task generate-schema` from the repository root to add placeholder descriptions // 2. replace all "PLACEHOLDER" values with the actual descriptions if possible -// 3. run `task generate:schema` again to regenerate the schema with acutal descriptions +// 3. run `task generate-schema` again to regenerate the schema with acutal descriptions func TestRequiredAnnotationsForNewFields(t *testing.T) { workdir := t.TempDir() annotationsPath := path.Join(workdir, "annotations.yml") diff --git a/tools/testmask/targets.go b/tools/testmask/targets.go index d01b1d4c7a..35d8bbcfc7 100644 --- a/tools/testmask/targets.go +++ b/tools/testmask/targets.go @@ -10,9 +10,8 @@ import ( "gopkg.in/yaml.v3" ) -// ciTargets lists the dash-separated CI output names whose trigger sets -// come from the corresponding Taskfile task's `sources:`. The task name is -// derived by replacing "-" with ":" (e.g. "test-exp-ssh" → "test:exp:ssh"). +// ciTargets lists the Taskfile task names whose `sources:` define the +// trigger set for their corresponding CI job of the same name. var ciTargets = []string{ "test-exp-aitools", "test-exp-ssh", @@ -57,14 +56,13 @@ func LoadTargetMappings(taskfilePath string) ([]targetMapping, error) { mappings := []targetMapping{ {prefixes: slices.Clone(commonTriggerPatterns), target: "test"}, } - for _, outputName := range ciTargets { - taskName := strings.ReplaceAll(outputName, "-", ":") - t, ok := tf.Tasks[taskName] + for _, name := range ciTargets { + t, ok := tf.Tasks[name] if !ok { - return nil, fmt.Errorf("task %q not found in %s", taskName, taskfilePath) + return nil, fmt.Errorf("task %q not found in %s", name, taskfilePath) } if len(t.Sources) == 0 { - return nil, fmt.Errorf("task %q in %s has no sources", taskName, taskfilePath) + return nil, fmt.Errorf("task %q in %s has no sources", name, taskfilePath) } prefixes := slices.Clone(commonTriggerPatterns) for _, src := range t.Sources { @@ -74,7 +72,7 @@ func LoadTargetMappings(taskfilePath string) ([]targetMapping, error) { } prefixes = append(prefixes, sourceToPrefix(s)) } - mappings = append(mappings, targetMapping{prefixes: prefixes, target: outputName}) + mappings = append(mappings, targetMapping{prefixes: prefixes, target: name}) } return mappings, nil } From 7e0dc9c76663d4a411169fe45eb57e1a4d56e05b Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Tue, 21 Apr 2026 12:38:47 +0200 Subject: [PATCH 32/45] Makefile: use .DEFAULT so the task wrapper actually fires The previous `%: @./task "$@"` pattern rule didn't trigger for phony targets in GNU Make 3.81 (Apple's default); `make test-unit` printed "Nothing to be done". `.DEFAULT` is the built-in hook for unmatched targets and fires reliably. Co-authored-by: Isaac --- Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Makefile b/Makefile index b1ce405b07..41fe170494 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,2 @@ -.PHONY: $(MAKECMDGOALS) -%: +.DEFAULT: @./task "$@" From 6f920d819f9485b919d76d9480cee1f0a9afb0fa Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Tue, 21 Apr 2026 14:01:54 +0200 Subject: [PATCH 33/45] tools: tidy duplicate require in go.mod Co-authored-by: Isaac --- tools/go.mod | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tools/go.mod b/tools/go.mod index 644cafaec1..fdb567331a 100644 --- a/tools/go.mod +++ b/tools/go.mod @@ -6,10 +6,7 @@ toolchain go1.25.9 require github.com/stretchr/testify v1.11.1 -require ( - github.com/stretchr/testify v1.11.1 - gopkg.in/yaml.v3 v3.0.1 -) +require gopkg.in/yaml.v3 v3.0.1 require ( 4d63.com/gocheckcompilerdirectives v1.3.0 // indirect From d155086171aecd12f11fea09d4f641f1389a4768 Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Tue, 21 Apr 2026 14:02:30 +0200 Subject: [PATCH 34/45] Taskfile: add `full` task for more complete dev loop Mirrors `default` but swaps in the non-incremental fmt/lint variants. Also tightens the `all:` description to mention regeneration scope (skips genkit) and test updates. Co-authored-by: Isaac --- Taskfile.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Taskfile.yml b/Taskfile.yml index 8c51e7ff57..ae07f29380 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -15,8 +15,16 @@ tasks: - task: lint-q - task: test-update + full: + desc: More complete dev loop + cmds: + - task: checks + - task: fmt + - task: lint + - task: test-update + all: - desc: Run all checks, full fmt, full lint, tests, and regeneration + desc: Run regeneration (except for genkit), all checks, lints and test updates cmds: # Skips generate-genkit (expensive, requires universe checkout, outputs are # committed). Run `./task generate` explicitly when codegen inputs change. From bb5fae3784d6af2c38ad7d21feeb09d176a61210 Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Tue, 21 Apr 2026 14:02:50 +0200 Subject: [PATCH 35/45] Taskfile: fail loudly on test-update errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drop the leading \`-\` on test-update and test-update-templates cmds. The dash tells Taskfile to ignore a non-zero exit, which masked broken acceptance tests — we want these to fail the dev loop. Co-authored-by: Isaac --- Taskfile.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Taskfile.yml b/Taskfile.yml index ae07f29380..2098afa521 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -398,12 +398,12 @@ tasks: test-update: desc: Update acceptance test output (local) cmds: - - "-go test ./acceptance -run '^TestAccept$' -update -timeout=${LOCAL_TIMEOUT:-30m}" + - "go test ./acceptance -run '^TestAccept$' -update -timeout=${LOCAL_TIMEOUT:-30m}" test-update-templates: desc: Update acceptance test template output cmds: - - "-go test ./acceptance -run '^TestAccept/bundle/templates' -update -timeout=${LOCAL_TIMEOUT:-30m}" + - "go test ./acceptance -run '^TestAccept/bundle/templates' -update -timeout=${LOCAL_TIMEOUT:-30m}" test-update-aws: desc: Update acceptance test output (integration, requires deco access) From 039a4b86cde5cfc2f0f991bd04ee3f4e5d2fcb9e Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Tue, 21 Apr 2026 14:03:30 +0200 Subject: [PATCH 36/45] Taskfile: drop generate-out-test-toml Removing as unused. out.test.toml is regenerated by the normal test-update flow. Co-authored-by: Isaac --- Taskfile.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Taskfile.yml b/Taskfile.yml index 2098afa521..441e089fe1 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -417,11 +417,6 @@ tasks: - task: test-update - task: test-update-aws - generate-out-test-toml: - desc: Regenerate out.test.toml files without running tests - cmds: - - "go test ./acceptance -run '^TestAccept$' -only-out-test-toml -timeout=${LOCAL_TIMEOUT:-30m}" - slowest: desc: Show 50 slowest tests from last run cmds: From 2010a4746e8532f9287cbd18e7341b30192db7a9 Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Tue, 21 Apr 2026 14:03:48 +0200 Subject: [PATCH 37/45] Taskfile: tighten sources for test-acc and test-update* Replace the broad \`**/*.go + acceptance/**\` source globs with the same curated list the \`build\` task uses (acceptance_test.go builds the CLI in-process via BuildCLI), plus acceptance/** for the test harness and fixtures, plus go.mod/go.sum. Two separate source lists because out.* files play different roles: - test-acc: out.* are golden inputs. A change to a committed out.* must re-run the test to confirm it still matches. - test-update*: out.* are outputs. The task rewrites them, so keeping them in sources would change the checksum each run and force re-execution on every invocation. The latter uses a shared &ACC_SOURCES_UPDATE YAML anchor across test-update, test-update-templates, and test-update-aws. Co-authored-by: Isaac --- Taskfile.yml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/Taskfile.yml b/Taskfile.yml index 441e089fe1..012a018f35 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -382,9 +382,19 @@ tasks: test-acc: desc: Run acceptance tests + # Sources mirror `build` (acceptance_test.go builds the CLI in-process via BuildCLI) + # plus acceptance/**. For test-acc the checked-in out.* files are golden inputs: + # changing them must re-run the test. test-update* excludes out.* because they + # are outputs there — see &ACC_SOURCES_UPDATE below. sources: - "**/*.go" + - exclude: "**/*_test.go" + - exclude: integration/** + - exclude: tools/** + - exclude: bundle/internal/tf/codegen/** - acceptance/** + - go.mod + - go.sum cmds: - | {{.GO_TOOL}} gotestsum \ @@ -397,16 +407,30 @@ tasks: test-update: desc: Update acceptance test output (local) + # Excludes out.* because the task rewrites them; keeping them in sources would + # invalidate the checksum and force a re-run on every invocation. + sources: &ACC_SOURCES_UPDATE + - "**/*.go" + - exclude: "**/*_test.go" + - exclude: integration/** + - exclude: tools/** + - exclude: bundle/internal/tf/codegen/** + - acceptance/** + - exclude: acceptance/**/out.* + - go.mod + - go.sum cmds: - "go test ./acceptance -run '^TestAccept$' -update -timeout=${LOCAL_TIMEOUT:-30m}" test-update-templates: desc: Update acceptance test template output + sources: *ACC_SOURCES_UPDATE cmds: - "go test ./acceptance -run '^TestAccept/bundle/templates' -update -timeout=${LOCAL_TIMEOUT:-30m}" test-update-aws: desc: Update acceptance test output (integration, requires deco access) + sources: *ACC_SOURCES_UPDATE cmds: - "deco env run -i -n aws-prod-ucws -- env DATABRICKS_TEST_SKIPLOCAL=1 go test ./acceptance -run ^TestAccept$ -update -timeout=1h -v" From 2134a5a732c615392b374786371e6d92dc58408c Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Tue, 21 Apr 2026 15:39:17 +0200 Subject: [PATCH 38/45] testmask: diff against empty tree SHA to avoid depending on HEAD~2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The test failed on shallow CI clones (default fetch-depth: 1) because HEAD~2 doesn't resolve. The well-known empty tree SHA (4b825dc642cb6eb9a060e54bf8d69288fbee4904) is always available to git regardless of clone depth, and diffing HEAD against it produces the full file set — still exercising the non-empty result path. Co-authored-by: Isaac --- tools/testmask/git_test.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tools/testmask/git_test.go b/tools/testmask/git_test.go index b62e9885ec..abf0bd1ba3 100644 --- a/tools/testmask/git_test.go +++ b/tools/testmask/git_test.go @@ -4,6 +4,11 @@ import ( "testing" ) +// gitEmptyTreeSHA is the well-known SHA of the empty tree object. Git resolves +// it without requiring a commit to reference it, so diffing against it works +// even on shallow clones where HEAD~N is unavailable (as in CI). +const gitEmptyTreeSHA = "4b825dc642cb6eb9a060e54bf8d69288fbee4904" + func TestGetChangedFiles(t *testing.T) { // Test with HEAD to HEAD - should return empty list result, err := GetChangedFiles("HEAD", "HEAD") @@ -15,8 +20,8 @@ func TestGetChangedFiles(t *testing.T) { t.Errorf("expected empty list, got %q", result) } - // Test with HEAD to HEAD~2 - should produce non-empty result if there are commits - result, err = GetChangedFiles("HEAD", "HEAD~2") + // Test against the empty tree - should produce non-empty result (all files in HEAD) + result, err = GetChangedFiles("HEAD", gitEmptyTreeSHA) if err != nil { t.Errorf("unable to run git: %q", err) return From 4d19c6b97af7f1660525e0a5e43f903a24e4ac80 Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Tue, 21 Apr 2026 15:45:14 +0200 Subject: [PATCH 39/45] Taskfile: reference ws-fix from generate-genkit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Addresses review feedback from @janniklasrose — dedupe the direct validate_whitespace.py --fix call. Co-authored-by: Isaac --- Taskfile.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Taskfile.yml b/Taskfile.yml index 012a018f35..b7f8610d2c 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -641,7 +641,7 @@ tasks: sed -i 's|tagging.py|internal/genkit/tagging.py|g' .github/workflows/tagging.yml fi - "{{.GO_TOOL}} yamlfmt .github/workflows/tagging.yml" - - ./tools/validate_whitespace.py --fix + - task: ws-fix # Refreshes out.fields.txt, which records the field paths / types emitted by # `bundle debug refschema` (see cmd/bundle/debug/refschema.go). It reflects From c7cc94cd458b6dac5f233a5d72f9c464beae9171 Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Tue, 21 Apr 2026 16:35:13 +0200 Subject: [PATCH 40/45] task wrapper: resolve modfile via script dirname instead of git Drops the \`git rev-parse --show-toplevel\` subshell in favor of \`dirname "$0"\`, which is simpler and works even outside a git repo (e.g. in archive extractions or release artifacts). Co-authored-by: Isaac --- task | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/task b/task index 140f73beaf..a0f8232ee3 100755 --- a/task +++ b/task @@ -1,2 +1,2 @@ #!/bin/sh -exec go tool -modfile="$(git rev-parse --show-toplevel)/tools/task/go.mod" task "$@" +exec go tool -modfile="$(dirname "$0")/tools/task/go.mod" task "$@" From 9d16402f4196be30d1813acd45b788b231938f5e Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Tue, 21 Apr 2026 16:46:54 +0200 Subject: [PATCH 41/45] docs: prefer ./task over bare task in code-fenced examples The system \`task\` binary in some PATHs is broken / missing; the repo's wrapper at ./task always works. Update AGENTS.md / CLAUDE.md, .agent/rules/auto-generated-files.md, bundle/docsgen/README.md, and the comment block in bundle/internal/schema/main_test.go. Co-authored-by: Isaac --- .agent/rules/auto-generated-files.md | 16 +++++++-------- AGENTS.md | 30 ++++++++++++++-------------- bundle/docsgen/README.md | 6 +++--- bundle/internal/schema/main_test.go | 4 ++-- 4 files changed, 28 insertions(+), 28 deletions(-) diff --git a/.agent/rules/auto-generated-files.md b/.agent/rules/auto-generated-files.md index 7140e2fb3c..bde566d68e 100644 --- a/.agent/rules/auto-generated-files.md +++ b/.agent/rules/auto-generated-files.md @@ -64,24 +64,24 @@ If a change is needed in any matched file: ### Core generation commands - Everything, in one shot: - - `task generate` — aggregator that runs all generators below + - `./task generate` — aggregator that runs all generators below - OpenAPI SDK/CLI command stubs and related generated artifacts: - - `task generate-genkit` + - `./task generate-genkit` - Includes generated `cmd/account/**`, `cmd/workspace/**`, `.gitattributes`, `internal/genkit/tagging.py`. - Direct engine generated YAML: - - `task generate-direct` (or `task generate-direct-apitypes`, `task generate-direct-resources`) + - `./task generate-direct` (or `./task generate-direct-apitypes`, `./task generate-direct-resources`) - Bundle schemas: - - `task generate-schema` - - `task generate-schema-docs` + - `./task generate-schema` + - `./task generate-schema-docs` - This can also refresh `bundle/internal/schema/annotations_openapi.yml` when OpenAPI annotation extraction is enabled. - Bundle docs: - - `task generate-docs` + - `./task generate-docs` - Validation generated code: - - `task generate-validation` + - `./task generate-validation` - Mock files: - `go run github.com/vektra/mockery/v2@b9df18e0f7b94f0bc11af3f379c8a9aea1e1e8da` - Python bundle codegen: - - `task pydabs-codegen` + - `./task pydabs-codegen` ### Acceptance and test generated outputs diff --git a/AGENTS.md b/AGENTS.md index 74b723a8b1..1eec48d0f5 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -12,27 +12,27 @@ When moving code from one place to another, please don't unnecessarily change th ### Building and Testing -- `task build` - Build the CLI binary -- `task test` - Run unit and acceptance tests for all packages +- `./task build` - Build the CLI binary +- `./task test` - Run unit and acceptance tests for all packages - `go test ./acceptance -run TestAccept/bundle/// -tail -test.v` - run a single acceptance test -- `task integration` - Run integration tests (requires environment variables) -- `task cover` - Generate test coverage reports +- `./task integration` - Run integration tests (requires environment variables) +- `./task cover` - Generate test coverage reports ### Code Quality -- `task lint` - Run full linter across all Go modules (root, tools, codegen) -- `task lint-q` - Run linter on changed files only (uses lintdiff.py, root module, with --fix) -- `task ws` - Run whitespace linter -- `task fmt` - Format all code (Go, Python, YAML) -- `task fmt-q` - Format changed files only (incremental Go + Python + YAML) -- `task checks` - Run quick checks (tidy, whitespace, links) +- `./task lint` - Run full linter across all Go modules (root, tools, codegen) +- `./task lint-q` - Run linter on changed files only (uses lintdiff.py, root module, with --fix) +- `./task ws` - Run whitespace linter +- `./task fmt` - Format all code (Go, Python, YAML) +- `./task fmt-q` - Format changed files only (incremental Go + Python + YAML) +- `./task checks` - Run quick checks (tidy, whitespace, links) ### Specialized Commands -- `task generate-schema` - Generate bundle JSON schema -- `task generate-docs` - Generate bundle documentation -- `task generate-genkit` - Run genkit to generate CLI commands and tagging workflow (requires universe repo) -- `task generate` - Run all generators +- `./task generate-schema` - Generate bundle JSON schema +- `./task generate-docs` - Generate bundle documentation +- `./task generate-genkit` - Run genkit to generate CLI commands and tagging workflow (requires universe repo) +- `./task generate` - Run all generators ### Git Commands @@ -79,7 +79,7 @@ GIT_EDITOR=true GIT_SEQUENCE_EDITOR=true VISUAL=true GIT_PAGER=cat git rebase or # Development Tips -- Use `task test-update` to regenerate acceptance test outputs after changes +- Use `./task test-update` to regenerate acceptance test outputs after changes - The CLI binary supports both `databricks` and `pipelines` command modes based on executable name - Comments should explain "why", not "what" — reviewers consistently reject comments that merely restate the code diff --git a/bundle/docsgen/README.md b/bundle/docsgen/README.md index 5d5517def2..0468945dc7 100644 --- a/bundle/docsgen/README.md +++ b/bundle/docsgen/README.md @@ -1,9 +1,9 @@ ## docs-autogen 1. Install [Golang](https://go.dev/doc/install) -2. Run `task generate-docs` from the repo +2. Run `./task generate-docs` from the repo 3. See generated documents in `./bundle/docsgen/output` directory -4. To change descriptions update content in `./bundle/internal/schema/annotations.yml` or `./bundle/internal/schema/annotations_openapi_overrides.yml` and re-run `task generate-docs` +4. To change descriptions update content in `./bundle/internal/schema/annotations.yml` or `./bundle/internal/schema/annotations_openapi_overrides.yml` and re-run `./task generate-docs` For simpler usage run it together with copy command to move resulting files to local `docs` repo. Note that it will overwrite any local changes in affected files. Example: @@ -76,4 +76,4 @@ github.com/databricks/cli/bundle/config.Bundle: ### TODO -Add file watcher to track changes in the annotation files and re-run `task generate-docs` script automtically +Add file watcher to track changes in the annotation files and re-run `./task generate-docs` script automtically diff --git a/bundle/internal/schema/main_test.go b/bundle/internal/schema/main_test.go index d37fa3d155..e9421e4c6e 100644 --- a/bundle/internal/schema/main_test.go +++ b/bundle/internal/schema/main_test.go @@ -43,9 +43,9 @@ func copyFile(src, dst string) error { // Checks whether descriptions are added for new config fields in the annotations.yml file // If this test fails either manually add descriptions to the `annotations.yml` or do the following: // 1. for fields described outside of CLI package fetch latest schema from the OpenAPI spec and add path to file to DATABRICKS_OPENAPI_SPEC env variable -// 2. run `task generate-schema` from the repository root to add placeholder descriptions +// 2. run `./task generate-schema` from the repository root to add placeholder descriptions // 2. replace all "PLACEHOLDER" values with the actual descriptions if possible -// 3. run `task generate-schema` again to regenerate the schema with acutal descriptions +// 3. run `./task generate-schema` again to regenerate the schema with acutal descriptions func TestRequiredAnnotationsForNewFields(t *testing.T) { workdir := t.TempDir() annotationsPath := path.Join(workdir, "annotations.yml") From ed7da79fb24a0cda173a3c002c4f4d2246f9cc98 Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Tue, 21 Apr 2026 16:59:16 +0200 Subject: [PATCH 42/45] lintdiff: hard-code nested module list Co-authored-by: Isaac --- tools/lintdiff.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/tools/lintdiff.py b/tools/lintdiff.py index 8c6092f9e4..aded17a285 100755 --- a/tools/lintdiff.py +++ b/tools/lintdiff.py @@ -13,6 +13,8 @@ import argparse import subprocess +NESTED_MODULES = ("bundle/internal/tf/codegen", "tools") + def parse_lines(cmd): # print("+ " + " ".join(cmd), file=sys.stderr, flush=True) @@ -58,14 +60,9 @@ def main(): filter_nested = "run" in cmd if changed is not None: - nested_modules = [] - if filter_nested: - nested_modules = sorted( - os.path.dirname(p) for p in parse_lines(["git", "ls-files", "--", "*/go.mod"]) or [] - ) def in_nested_module(path): - return any(path == m or path.startswith(m + "/") for m in nested_modules) + return filter_nested and any(path == m or path.startswith(m + "/") for m in NESTED_MODULES) # We need to pass packages to golangci-lint, not individual files. # QQQ for lint we should also pass all dependent packages From 2457e0c217e109025d1eadcef6894cdc624794f5 Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Tue, 21 Apr 2026 17:03:57 +0200 Subject: [PATCH 43/45] Taskfile: drop nested golangci configs, inherit root with gocritic off Why: the minimal configs in tools/ and bundle/internal/tf/codegen/ existed only to opt nested modules out of root's ruleguard check (whose rules path is cwd-relative and unresolvable from those dirs). Disabling gocritic via --disable is equivalent and removes the duplicated enable lists. Co-authored-by: Isaac --- Taskfile.yml | 12 ++++++++---- bundle/internal/tf/codegen/.golangci.yaml | 22 ---------------------- tools/.golangci.yaml | 22 ---------------------- 3 files changed, 8 insertions(+), 48 deletions(-) delete mode 100644 bundle/internal/tf/codegen/.golangci.yaml delete mode 100644 tools/.golangci.yaml diff --git a/Taskfile.yml b/Taskfile.yml index b7f8610d2c..7710dbe083 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -94,13 +94,15 @@ tasks: TMPDIR: '{{.ROOT_DIR}}/.tmp/golangci-lint-tools' sources: - "**/*.go" - - .golangci.yaml + - '{{.ROOT_DIR}}/.golangci.yaml' - go.mod - go.sum cmds: - cmd: mkdir -p "{{.TMPDIR}}" silent: true - - TMPDIR="{{.TMPDIR}}" {{.GO_TOOL}} golangci-lint run ./... + # gocritic is disabled because root's ruleguard rules path is cwd-relative + # and cannot be resolved from this nested module. + - TMPDIR="{{.TMPDIR}}" {{.GO_TOOL}} golangci-lint run --disable gocritic ./... lint-go-codegen: desc: Lint Go files in bundle/internal/tf/codegen module @@ -109,13 +111,15 @@ tasks: TMPDIR: '{{.ROOT_DIR}}/.tmp/golangci-lint-codegen' sources: - "**/*.go" - - .golangci.yaml + - '{{.ROOT_DIR}}/.golangci.yaml' - go.mod - go.sum cmds: - cmd: mkdir -p "{{.TMPDIR}}" silent: true - - TMPDIR="{{.TMPDIR}}" {{.GO_TOOL}} golangci-lint run ./... + # gocritic is disabled because root's ruleguard rules path is cwd-relative + # and cannot be resolved from this nested module. + - TMPDIR="{{.TMPDIR}}" {{.GO_TOOL}} golangci-lint run --disable gocritic ./... lint-q-go-root: desc: Lint changed Go files in root module (diff vs main, with --fix). Does not check tools/ or bundle/internal/tf/codegen — use `lint` for full coverage. diff --git a/bundle/internal/tf/codegen/.golangci.yaml b/bundle/internal/tf/codegen/.golangci.yaml deleted file mode 100644 index 49ae04f476..0000000000 --- a/bundle/internal/tf/codegen/.golangci.yaml +++ /dev/null @@ -1,22 +0,0 @@ -version: "2" -linters: - default: none - enable: - - bodyclose - - errcheck - - gocritic - - govet - - ineffassign - - intrange - - mirror - - perfsprint - - revive - - staticcheck - - testifylint - - unconvert - - unused - - copyloopvar - settings: - gocritic: - disabled-checks: - - ruleguard diff --git a/tools/.golangci.yaml b/tools/.golangci.yaml deleted file mode 100644 index 49ae04f476..0000000000 --- a/tools/.golangci.yaml +++ /dev/null @@ -1,22 +0,0 @@ -version: "2" -linters: - default: none - enable: - - bodyclose - - errcheck - - gocritic - - govet - - ineffassign - - intrange - - mirror - - perfsprint - - revive - - staticcheck - - testifylint - - unconvert - - unused - - copyloopvar - settings: - gocritic: - disabled-checks: - - ruleguard From f67fdf18efd020889414cb1d4684769f1a881b73 Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Wed, 22 Apr 2026 11:32:43 +0200 Subject: [PATCH 44/45] Taskfile: anchor duplicated source lists, fix test-unit-root cache - Introduce &BUILD_SOURCES, &ROOT_LINT_SOURCES, &FMT_GO_SOURCES, &SCHEMA_SOURCES to dedupe identical source lists across paired full/quick variants and build/snapshot. - Add go.mod and go.sum to test-unit-root sources so SDK bumps invalidate the checksum cache (test-unit-tools and test-unit-codegen already list them). Co-authored-by: Isaac --- Taskfile.yml | 43 ++++++++++++------------------------------- 1 file changed, 12 insertions(+), 31 deletions(-) diff --git a/Taskfile.yml b/Taskfile.yml index 7710dbe083..e56c658a2c 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -77,7 +77,7 @@ tasks: desc: Lint Go files in the root module vars: TMPDIR: '{{.ROOT_DIR}}/.tmp/golangci-lint-root' - sources: + sources: &ROOT_LINT_SOURCES - "**/*.go" - exclude: tools/** - exclude: bundle/internal/tf/codegen/** @@ -125,11 +125,7 @@ tasks: desc: Lint changed Go files in root module (diff vs main, with --fix). Does not check tools/ or bundle/internal/tf/codegen — use `lint` for full coverage. vars: TMPDIR: '{{.ROOT_DIR}}/.tmp/golangci-lint-root' - sources: - - "**/*.go" - - exclude: tools/** - - exclude: bundle/internal/tf/codegen/** - - .golangci.yaml + sources: *ROOT_LINT_SOURCES cmds: - cmd: mkdir -p "{{.TMPDIR}}" silent: true @@ -157,7 +153,7 @@ tasks: # in a single invocation. fmt-go: desc: Format all Go files - sources: + sources: &FMT_GO_SOURCES - "**/*.go" - .golangci.yaml cmds: @@ -165,9 +161,7 @@ tasks: fmt-q-go: desc: Format changed Go files (diff vs main) - sources: - - "**/*.go" - - .golangci.yaml + sources: *FMT_GO_SOURCES cmds: - "./tools/lintdiff.py {{.GO_TOOL}} golangci-lint fmt" @@ -256,7 +250,7 @@ tasks: build: desc: Build the CLI binary deps: ['tidy-root'] - sources: + sources: &BUILD_SOURCES - "**/*.go" - exclude: "**/*_test.go" - exclude: acceptance/** @@ -273,15 +267,7 @@ tasks: snapshot: desc: Build snapshot binary to .databricks/databricks deps: ['tidy-root'] - sources: - - "**/*.go" - - exclude: "**/*_test.go" - - exclude: acceptance/** - - exclude: integration/** - - exclude: tools/** - - exclude: bundle/internal/tf/codegen/** - - go.mod - - go.sum + sources: *BUILD_SOURCES generates: - .databricks/databricks cmds: @@ -290,6 +276,8 @@ tasks: snapshot-release: desc: Build release binaries locally without uploading deps: ['tidy-root'] + # Same as BUILD_SOURCES + .goreleaser.yaml (list concat is not expressible + # via YAML anchor alone, so the shared block is duplicated here). sources: - "**/*.go" - exclude: "**/*_test.go" @@ -340,6 +328,8 @@ tasks: - "**/*.go" - exclude: tools/** - exclude: bundle/internal/tf/codegen/** + - go.mod + - go.sum cmds: - | {{.GO_TOOL}} gotestsum \ @@ -667,7 +657,7 @@ tasks: generate-schema: desc: Generate bundle JSON schema - sources: + sources: &SCHEMA_SOURCES - bundle/internal/schema/*.go - exclude: bundle/internal/schema/*_test.go - bundle/internal/schema/annotations*.yml @@ -684,16 +674,7 @@ tasks: generate-schema-docs: desc: Generate bundle JSON schema for documentation - sources: - - bundle/internal/schema/*.go - - exclude: bundle/internal/schema/*_test.go - - bundle/internal/schema/annotations*.yml - - bundle/config/**/*.go - - exclude: bundle/config/**/*_test.go - - libs/jsonschema/**/*.go - - exclude: libs/jsonschema/**/*_test.go - - go.mod - - go.sum + sources: *SCHEMA_SOURCES generates: - bundle/schema/jsonschema_for_docs.json cmds: From d3a301bab2f299b4bb842f0e3672fcf1fb1e9c0d Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Wed, 22 Apr 2026 17:15:54 +0200 Subject: [PATCH 45/45] "make" (no args) runs ./task (no args) --- Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile b/Makefile index 41fe170494..6c7e2dc63a 100644 --- a/Makefile +++ b/Makefile @@ -1,2 +1,5 @@ +default: + ./task + .DEFAULT: @./task "$@"