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.
# 1. Formatting and checks (CI runs fmt, not fmt-q)
./task fmt
./task checks
# 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)
./task test
# 4. If you changed bundle config structs, schema, or direct-engine resource code:
./task generate-schema
./task generate-direct
# 5. If you changed files in python/:
./task pydabs-codegen pydabs-test pydabs-lint pydabs-docs
# 6. If you changed cmd/aitools/, libs/aitools/, experimental/aitools/, or experimental/ssh/:
./task test-exp-aitools # only if aitools code changed (top-level or experimental)
./task test-exp-ssh # only if ssh code changed
Final cleanup scan
After the commands above pass, scrub the diff before pushing. The quick version: run git diff @{u} and read through what you added. Specifically:
Debug prints: look for newly added fmt.Print, fmt.Printf, fmt.Println, log.Print, log.Printf, log.Println, or bare println(...) calls. A regex that scans only added lines against your upstream branch:
git diff @{u} -- '*.go' | rg '^\+.*\b(fmt|log)\.(Print|Printf|Println)\b|^\+.*\bprintln\('
If you have no upstream yet, substitute the intended base (e.g. origin/main) for @{u}.
Commented-out code: delete it. If it's needed for reference, it lives in git history.
TODOs without a ticket: either add a ticket reference (e.g. // TODO(DECO-1234): ...) or remove the TODO. Un-tracked TODOs rot.
Unintended files: review git status and git diff --stat to confirm only the files you meant to change are staged.
PR description
Follow .github/PULL_REQUEST_TEMPLATE.md exactly. Use its section headings (## Changes, ## Why, ## Tests) in the same order, and fill each one in. Do not invent new sections (## Summary, ## Test plan, etc.), do not drop sections, and do not leave the HTML comment placeholders in the final body — replace them with real content. If a section genuinely does not apply (e.g. a docs-only change has no test steps), say so explicitly under that heading rather than removing it.
RULE: Be concise in the PR summary. Overly verbose descriptions tend to be ignored by reviewers. Let the diff speak for itself and only describe at a high level what you have implemented/what components were touched.
When using gh pr create, read .github/PULL_REQUEST_TEMPLATE.md first and base --body on it.
If an agent (you) authored or substantially helped author the PR, disclose it on the last line of the body, e.g. _This PR was written by Claude Code._ or _PR description drafted with Claude Code._. Be honest about the level of involvement — "written by" vs. "drafted with" vs. "reviewed by" — and keep it to a single italicized line so it doesn't crowd the template sections.
Changelog entry
Add a changelog fragment under .nextchanges/ when your change is user-visible. Each PR adds its own file, so entries never conflict between PRs. The release renders these fragments into the real CHANGELOG.md, so never hand-edit CHANGELOG.md directly.
When to add an entry:
- New or changed CLI command, flag, or subcommand behavior
- New or changed bundle config field, schema, or engine behavior
- New direct dependency (annotate under
Dependency updates)
- Bug fix that users will notice
When to skip:
- Experimental commands (under
experimental/): no entry until the feature graduates out of experimental
- Pure refactors, internal renames, test-only changes, and doc-only changes
- Auto-generated output changes without a corresponding user-facing change
How to add:
- Create
.nextchanges/<section>/<name>.md, picking the section folder that fits: cli, bundles, dependency-updates, notable-changes, or api-changes. <name> is arbitrary (a feature name or your PR number) — just keep it unique.
- Write a single line in user-facing language, no Jira links: start it with a
* bullet marker and end it with a period.
- Voice and tense: imperative mood, active voice. Lead with a verb that names the change —
Add, Fix, Bump, Remove, Deprecate, Support, Reject, Warn — and describe the user-facing effect, not the implementation. Never use past tense (Added/Fixed) or first person (we/I/our). When a change reads better as a resulting behavior than as a verb, lead with the affected command, flag, or field in the present tense with "now".
- GOOD: Add support for the
cluster_policies resource type.
- GOOD: Fix
--force-lock being ignored when set in databricks.yml.
- GOOD:
bundle plan now ignores the output-only securable_kind field during drift detection.
- BAD: Added support for cluster policies. — past tense; write "Add".
- BAD: We now reject secret scopes that name no principal. — first person; write "Reject secret scopes that name no principal."
- A trailing PR link is required whenever the change is associated with a PR, and the introducing PR must be among the linked ones (the checker infers it and fails if it's missing) — enforced in CI (every PR and
main) and locally once your branch has an open PR. Write the full markdown link at the very end, after the period: ([#NNNN](https://github.com/databricks/cli/pull/NNNN)) (your PR number). For an entry spanning several PRs, list them comma-separated: ([#NNNN](…), [#MMMM](…)). Every #NNNN reference must be a full markdown link — a bare or paren-wrapped #NNNN is rejected.
- See
.nextchanges/README.md for details.
1---2name: pr-checklist3description: Checklist to run before submitting a PR4---56Before 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.78```bash9# 1. Formatting and checks (CI runs fmt, not fmt-q)10./task fmt11./task checks1213# 2. Linting (CI runs full golangci-lint across all modules, not the diff-only wrapper)14./task lint1516# 3. Tests (CI runs with both deployment engines)17./task test1819# 4. If you changed bundle config structs, schema, or direct-engine resource code:20./task generate-schema21./task generate-direct2223# 5. If you changed files in python/:24./task pydabs-codegen pydabs-test pydabs-lint pydabs-docs2526# 6. If you changed cmd/aitools/, libs/aitools/, experimental/aitools/, or experimental/ssh/:27./task test-exp-aitools # only if aitools code changed (top-level or experimental)28./task test-exp-ssh # only if ssh code changed29```3031## Final cleanup scan3233After the commands above pass, scrub the diff before pushing. The quick version: run `git diff @{u}` and read through what you added. Specifically:3435- **Debug prints**: look for newly added `fmt.Print`, `fmt.Printf`, `fmt.Println`, `log.Print`, `log.Printf`, `log.Println`, or bare `println(...)` calls. A regex that scans only added lines against your upstream branch:3637 ```bash38 git diff @{u} -- '*.go' | rg '^\+.*\b(fmt|log)\.(Print|Printf|Println)\b|^\+.*\bprintln\('39 ```4041 If you have no upstream yet, substitute the intended base (e.g. `origin/main`) for `@{u}`.42- **Commented-out code**: delete it. If it's needed for reference, it lives in git history.43- **TODOs without a ticket**: either add a ticket reference (e.g. `// TODO(DECO-1234): ...`) or remove the TODO. Un-tracked TODOs rot.44- **Unintended files**: review `git status` and `git diff --stat` to confirm only the files you meant to change are staged.4546## PR description4748Follow `.github/PULL_REQUEST_TEMPLATE.md` exactly. Use its section headings (`## Changes`, `## Why`, `## Tests`) in the same order, and fill each one in. Do not invent new sections (`## Summary`, `## Test plan`, etc.), do not drop sections, and do not leave the HTML comment placeholders in the final body — replace them with real content. If a section genuinely does not apply (e.g. a docs-only change has no test steps), say so explicitly under that heading rather than removing it.4950**RULE: Be concise in the PR summary.** Overly verbose descriptions tend to be ignored by reviewers. Let the diff speak for itself and only describe at a high level what you have implemented/what components were touched.5152When using `gh pr create`, read `.github/PULL_REQUEST_TEMPLATE.md` first and base `--body` on it.5354If an agent (you) authored or substantially helped author the PR, disclose it on the last line of the body, e.g. `_This PR was written by Claude Code._` or `_PR description drafted with Claude Code._`. Be honest about the level of involvement — "written by" vs. "drafted with" vs. "reviewed by" — and keep it to a single italicized line so it doesn't crowd the template sections.5556## Changelog entry5758Add a changelog fragment under `.nextchanges/` when your change is user-visible. Each PR adds its own file, so entries never conflict between PRs. The release renders these fragments into the real `CHANGELOG.md`, so never hand-edit `CHANGELOG.md` directly.5960**When to add an entry:**61- New or changed CLI command, flag, or subcommand behavior62- New or changed bundle config field, schema, or engine behavior63- New direct dependency (annotate under `Dependency updates`)64- Bug fix that users will notice6566**When to skip:**67- Experimental commands (under `experimental/`): no entry until the feature graduates out of experimental68- Pure refactors, internal renames, test-only changes, and doc-only changes69- Auto-generated output changes without a corresponding user-facing change7071**How to add:**72- Create `.nextchanges/<section>/<name>.md`, picking the section folder that fits: `cli`, `bundles`, `dependency-updates`, `notable-changes`, or `api-changes`. `<name>` is arbitrary (a feature name or your PR number) — just keep it unique.73- Write a single line in user-facing language, no Jira links: start it with a `* ` bullet marker and end it with a period.74- **Voice and tense: imperative mood, active voice.** Lead with a verb that names the change — `Add`, `Fix`, `Bump`, `Remove`, `Deprecate`, `Support`, `Reject`, `Warn` — and describe the user-facing effect, not the implementation. Never use past tense (`Added`/`Fixed`) or first person (`we`/`I`/`our`). When a change reads better as a resulting behavior than as a verb, lead with the affected command, flag, or field in the present tense with "now".75 - GOOD: Add support for the `cluster_policies` resource type.76 - GOOD: Fix `--force-lock` being ignored when set in `databricks.yml`.77 - GOOD: `bundle plan` now ignores the output-only `securable_kind` field during drift detection.78 - BAD: Added support for cluster policies. — past tense; write "Add".79 - BAD: We now reject secret scopes that name no principal. — first person; write "Reject secret scopes that name no principal."80- A trailing PR link is required whenever the change is associated with a PR, and the introducing PR must be among the linked ones (the checker infers it and fails if it's missing) — enforced in CI (every PR and `main`) and locally once your branch has an open PR. Write the full markdown link at the very end, after the period: `([#NNNN](https://github.com/databricks/cli/pull/NNNN))` (your PR number). For an entry spanning several PRs, list them comma-separated: `([#NNNN](…), [#MMMM](…))`. Every `#NNNN` reference must be a full markdown link — a bare or paren-wrapped `#NNNN` is rejected.81- See `.nextchanges/README.md` for details.