Replace Makefile with Taskfile.yml and move all generation-related logic there#5050
Replace Makefile with Taskfile.yml and move all generation-related logic there#5050
Conversation
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
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 <target>` 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
Replace `make <target>` with `go tool -modfile=tools/task/go.mod task <target>` 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
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
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
Shortens `go tool -modfile=tools/task/go.mod task <target>` to `./task <target>` and resolves the modfile via `git rev-parse --show-toplevel` so the script works from any subdirectory. Co-authored-by: Isaac
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
- 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
Co-authored-by: Isaac
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
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
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: <pattern>` 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
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
…efault - 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
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
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
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
- 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
- `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
Mirrors main's e24ae4e (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
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
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
…nerate.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
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
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
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
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
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
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
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
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
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
Co-authored-by: Isaac
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
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
Removing as unused. out.test.toml is regenerated by the normal test-update flow. Co-authored-by: Isaac
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
| @@ -1,3 +1,3 @@ | |||
| --- | |||
| description: Rules for how to deal with auto-generated files | |||
| globs: | |||
There was a problem hiding this comment.
Let's add a task that parses Taskfile.yml to auto-gen this?
There was a problem hiding this comment.
this could be a follow up
| generates: | ||
| - test-output.json | ||
| cmds: | ||
| - cat test-output-unit.json test-output-acc.json > test-output.json |
There was a problem hiding this comment.
cating two JSON doesn't create a JSON. Better to use jq here (ditto for others)
There was a problem hiding this comment.
these are json-lines files
There was a problem hiding this comment.
should we use .jsonl then?
There was a problem hiding this comment.
we could rename, but out of scope there (and might need updating other places like deco repo)
| 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 |
There was a problem hiding this comment.
can we reference ws-fix task?
The test failed on shallow CI clones (default fetch-depth: 1) because HEAD~2 doesn't resolve. The well-known empty tree SHA (4b825dc) 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
Addresses review feedback from @janniklasrose — dedupe the direct validate_whitespace.py --fix call. Co-authored-by: Isaac
| generates: | ||
| - test-output.json | ||
| cmds: | ||
| - cat test-output-unit.json test-output-acc.json > test-output.json |
There was a problem hiding this comment.
should we use .jsonl then?
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
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
Co-authored-by: Isaac
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
- 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
simonfaltum
left a comment
There was a problem hiding this comment.
Deep review (Isaac + Cursor, 2-round swarm)
Verdict: Not ready yet
Summary: 2 Critical | 9 Major | 2 Gap (Major) | 3 Nit | 4 Suggestion
Two independent reviewers (Isaac and Cursor) produced findings in parallel, then cross-reviewed each other's work, verifying claims against the code before agreeing / disagreeing. Inline comments follow below on specific lines. A few points that don't map cleanly to a single line:
Themes
- Makefile wrapper is lossy. Plain
makenow errors (.DEFAULTis a catch-all, not a default goal), andmake wsfixroutes to a non-existent task (renamed tows-fix). Either commit to a proper compat shim or drop the wrapper. - Windows CI path is broken.
./taskis a POSIX shell script; the Windows matrix legs inpush.ymldon't setshell: bashand default to pwsh. On main today these callmake(an.exe). - CI trigger graph is self-blind.
tools/testmaskonly treatsgo.mod/go.sum/setup-build-environment/as "common trigger" patterns. Changes toTaskfile.yml, thetasklauncher, ortools/testmask/**itself fall through totestonly, skipping specialized jobs (test-exp-aitools,test-exp-ssh,test-pipelines) precisely when their trigger or definition changed. Ironically this very PR would skip its own specialized tests if landed as-is. - Similarly for python CI:
python_push.ymlstill filters only onpaths: python/**but thepydabs-*task bodies now live in rootTaskfile.yml. generate-genkitshell rewrite subtly changes semantics. The old MakefileA && B || C && Dalways ranD(thegit checkout). The new groupedA && B || (C && D)skipsDwhen the SHA is already local — so genkit can build from whatever revision the user has checked out. Minimal shell repro confirmed.default/fulldev loops mutate goldens. They invoketest-update, nottest. Bare./taskcan silently bless acceptance-output regressions.- Cache source-list patterns are often wrong:
ROOT_LINT_SOURCESomits rootgo.mod/go.sum;pydabs-codegenhas overlappingsources:andgenerates:;generate-genkitsources missgo.mod/go.sumthat its embedded consistency assertion reads.
Findings dropped on cross-review (for transparency)
./task lintdropping--timeout=15m— verified:golangci-lint v2.5.0's--timeoutis now "Disabled by default," so no regression.generate-refschemalosing the old-ignore-errors prefix — verified:libs/testdiff's-updatemode overwrites goldens on mismatch rather than failing, so the-was masking real errors, not providing needed resilience../task --force generate-schemain CI — correct pattern forgenerator && git diff --exit-codeverification jobs; cache hits would make the check a no-op.make VAR=VALdropping variables — GNU make does forward command-line variables to the delegated child; the issue is only the "no default goal" + "ws-fix rename" points.
Full synthesis: see detailed inline comments below.
| @@ -0,0 +1,2 @@ | |||
| #!/bin/sh | |||
There was a problem hiding this comment.
[Critical] Windows CI jobs call a POSIX-only launcher
./task is #!/bin/sh, but .github/workflows/push.yml Windows matrix jobs (test, test-exp-ssh, test-pipelines) invoke ./task … directly. On GitHub Actions, Windows run: steps default to pwsh (no workflow-level defaults.run.shell: bash, and only one per-step shell: bash exists in push.yml — line 153, the git diff step). pwsh can't invoke an extensionless shebang script.
On main today these steps call make (a native .exe resolvable under pwsh), so this is a genuine regression. Note: the composite setup-build-environment/action.yml:41-42 does set shell: bash for ./task install-pythons — the author knew the issue at that site but missed the job-level call sites.
Suggested fix: add a task.cmd / PowerShell wrapper next to task, OR add shell: bash to every Windows run: ./task … step, OR set defaults.run.shell: bash at the job level for Windows matrix legs.
Found by: Cursor, Confirmed by: Isaac
There was a problem hiding this comment.
Windows CI tests did pass on the PR though.
| 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)) |
There was a problem hiding this comment.
[Critical] generate-genkit can build from the wrong universe revision
The old Makefile pattern A && B || C && D always ran D (the git checkout) regardless of whether the SHA was already local. The new grouped form is A && B || (C && D), which skips D when git cat-file -e succeeds. Consequence: if the requested OpenAPI SHA already exists in the local universe clone but isn't currently checked out, the task skips the checkout and builds genkit against whatever revision the user had checked out previously.
Minimal sh repro (verified):
- Old
true && true || true && echo X→ printsX. - New
true && true || (true && echo X)→ does NOT printX.
This is a silent generator correctness bug — output diverges from .codegen/_openapi_sha.
Suggested fix: use explicit control flow so the checkout is unconditional after the existence check:
if ! git cat-file -e $(cat .../_openapi_sha) 2>/dev/null; then
git fetch --filter=blob:none origin master
fi
git checkout $(cat .../_openapi_sha)Found by: Cursor, Confirmed by: Isaac (with repro)
| .PHONY: bench10_summary | ||
| bench10_summary: bench10.log | ||
| ./tools/bench_parse.py $< | ||
| .DEFAULT: |
There was a problem hiding this comment.
[Major] Makefile compatibility wrapper is not actually backwards-compatible
Two separate breaks, both verified on the PR branch:
makewith no target now fails:make: *** No targets. Stop.GNU.DEFAULTis a catch-all for named unmatched targets; it is not a default goal. The old Makefile haddefault: checks fmt lint.make wsfixforwards to./task wsfix, but the task was renamed tows-fix. Somake wsfixnow errors:task: Task "wsfix" does not exist. Did you mean "ws-fix"?→make: *** [wsfix] Error 200.wsfixappears in the workdir CLAUDE.md and was called directly by the now-deletedtools/post-generate.sh. No migration alias exists.
(Cross-review note: Isaac's original R1 also claimed make VAR=VAL target drops variables; Cursor verified this part was wrong — GNU make does forward command-line variables to delegated children. The issue is just .DEFAULT vs default goal and the wsfix rename.)
Suggested fix: either (a) add .DEFAULT_GOAL := default + a default: ; @./task rule and keep aliases for renamed legacy targets (wsfix: ; @./task ws-fix), or (b) delete the Makefile and let make's own error point users to ./task. The current half-wrapper is the worst of both.
Found by: Isaac + Cursor (both)
| 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 './task generate-out-test-toml' to update." |
There was a problem hiding this comment.
[Major] CI error message tells developers to run a task that does not exist
This error message says Run './task generate-out-test-toml' to update., but no such task exists in Taskfile.yml. The old main:Makefile had it (go test ./acceptance -run '^TestAccept$$' -only-out-test-toml); it was dropped in the migration.
Verified by running ./task generate-out-test-toml on the PR branch: it exits 200 with Task does not exist. Developers who hit this CI failure will follow the message into a second error.
(Also: .agent/rules/auto-generated-files.md on main mentions make generate-out-test-toml; that would route through .DEFAULT and hit the same dead end.)
Suggested fix: port the generate-out-test-toml target from the old Makefile into Taskfile.yml (it's a one-line go test invocation), and update agent docs if they still reference the old command.
Found by: Isaac (cross-review, R2)
| default: | ||
| desc: Quick dev loop (checks, formatters, incremental lint, tests). Use `all` for the full suite. | ||
| cmds: | ||
| - task: checks | ||
| - task: fmt-q | ||
| - task: lint-q | ||
| - task: test-update | ||
|
|
||
| full: | ||
| desc: More complete dev loop | ||
| cmds: | ||
| - task: checks | ||
| - task: fmt | ||
| - task: lint | ||
| - task: test-update |
There was a problem hiding this comment.
[Major] default / full dev loops rewrite acceptance goldens instead of verifying them
Both default ("Quick dev loop") and full invoke test-update rather than test. In -update mode, libs/testdiff/golden.go:45-50 overwrites expected files on mismatch instead of failing.
So a developer running bare ./task (the default target) can silently bless acceptance-output regressions. default is the implicit entrypoint for agent workflows — it needs to be verification-only.
Suggested fix: have default / full run test (verification), not test-update (mutation). If a "regen then verify" loop is useful, make it an explicitly named mutating task like update.
Found by: Cursor (cross-review, R2)
| # Local development notes, tmp | ||
| /pr-* | ||
| /tmp/ | ||
| /.tmp/ |
There was a problem hiding this comment.
[Nit] /tmp/ (pre-existing) and /.tmp/ (new) have different semantics
/tmp/ (line 63, pre-existing) is developer scratch; /.tmp/ (this line, new) is the per-module golangci-lint TMPDIR root configured in Taskfile.yml. Readers can't tell them apart from the current comment (line 61: # Local development notes, tmp).
Suggested fix: add an explanatory comment next to /.tmp/, e.g. # Taskfile cache for per-module golangci-lint TMPDIR (see Taskfile.yml).
Found by: Isaac (R1)
| fmt-q-go: | ||
| desc: Format changed Go files (diff vs main) | ||
| sources: *FMT_GO_SOURCES | ||
| cmds: | ||
| - "./tools/lintdiff.py {{.GO_TOOL}} golangci-lint fmt" |
There was a problem hiding this comment.
[Nit] fmt-q-go shares *FMT_GO_SOURCES with fmt-go; identical checksums mean fmt-q-go gets cached as "done" after fmt-go
Both tasks declare identical sources: via the same anchor. Once fmt-go has run, go-task's checksum cache will treat fmt-q-go as already up-to-date with the same checksum, even though the two have different semantics (full fmt vs diff-only fmt).
Low impact, but a user who runs fmt-go and then explicitly asks for fmt-q-go gets a no-op.
Suggested fix: either (a) give fmt-q-go a distinguishing source (e.g. .git/HEAD so branch changes invalidate it), or (b) set method: none on fmt-q-go so it always runs (it's cheap when nothing changed).
Found by: Isaac (R1), Confirmed by: Cursor (R2)
| import argparse | ||
| import subprocess | ||
|
|
||
| NESTED_MODULES = ("bundle/internal/tf/codegen", "tools") |
There was a problem hiding this comment.
[Nit] NESTED_MODULES is prefix-based but looks explicit
NESTED_MODULES = ("bundle/internal/tf/codegen", "tools") — the membership check at line 65 matches path == m or path.startswith(m + "/"), so it correctly catches tools/task/go.mod via the tools/ prefix. That's four real nested modules covered by two entries.
A future contributor adding a module outside these two prefixes will silently miss it; one adding a sibling to tools/task/ might not realize the prefix semantics and add a redundant entry.
Suggested fix: add a comment documenting the prefix-based semantics, or replace with a dynamic walker that discovers go.mod files (excluding the root).
Found by: Isaac (cross-review, R2)
| # .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 |
There was a problem hiding this comment.
[Suggestion] generate-schema-docs silently loses sinceVersion annotations on tag-less checkouts
The old tools/post-generate.sh (deleted in this PR) ran git fetch origin 'refs/tags/v*:refs/tags/v*' before invoking schema-for-docs. bundle/internal/schema/since_version.go:78-99 shells out to git tag --list 'v*' and git show <tag>:… to compute sinceVersion fields.
With no tags present (e.g., a fresh shallow clone), getVersionTags returns empty and the generated jsonschema_for_docs.json silently drops sinceVersion fields — no error.
CI is unaffected because the validate-generated check runs ./task --force generate-schema without --docs, but local ./task generate now produces subtly different jsonschema_for_docs.json output on tag-less checkouts.
Suggested fix: either add git fetch --tags as a pre-step in generate-schema-docs, or have computeSinceVersions log a warning when it sees zero tags but nonzero commit history.
Found by: Isaac (cross-review, R2)
| 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 |
There was a problem hiding this comment.
[Suggestion] Concurrent ./task test* runs share worktree-level output files
test-unit cats three per-module JSON files into test-output-unit.json (line 323); test then cats test-output-unit.json and test-output-acc.json into test-output.json (line 311). The three specialized test tasks (test-exp-aitools, test-exp-ssh, test-pipelines) all also end with cat ... > test-output.json.
Two agents running ./task test* (or mixes of them) in the same worktree will interleave writes — gotestsum --jsonfile opens-and-truncates. Cursor correctly noted origin/main already had this race via make test, so it's pre-existing, not a new Taskfile regression.
Still worth improving given the PR's stated motivation ("faster verification after agent work") specifically incentivizes concurrent invocations.
Suggested fix: write per-run JSON into .task/run-<id>/test-output-*.json and have the aggregator cat from there. Or at minimum, document that concurrent test* invocations in the same worktree are unsupported.
Found by: Isaac (R1), scope-corrected by Cursor (R2)
Each task describes inputs (sources) and outputs as precise as possible.
The tasks mostly match what we had in Makefile but slightly more consistent approach:
This also consolidates all knowledge about generation in one place:
The runner (go-task) is packaged as a go tool, no installation need. Shortcut ./task is available to run it. Makefile is temporarily a wrapper that calls ./task.
This enables caching - go-task will only re-run if sources changed. This helps when checking after agent work - if they did run linters / tests already, then running ./task is very quick.
~/work/cli-trees/task-file % time ./task
…
./task 612.63s user 310.22s system 726% cpu 2:06.95 total
~/work/cli-trees/task-file % time ./task
…
./task 2.43s user 10.58s system 133% cpu 9.727 total
Additionally, all golangci-lint tasks are fixed to use per-worktree & per-submodule tmp directory, which enables parallel runs within worktree and across worktrees.