Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
99cadc3
bundle/fuzz: add create-payload parity fuzz test for terraform vs direct
radakam Jun 23, 2026
495d152
bundle/fuzz: fix lint (intrange, perfsprint) and correct num_workers …
radakam Jun 23, 2026
df8bc36
bundle/fuzz: wire parity tests into CI and harden harness
radakam Jun 23, 2026
a24e58e
bundle/fuzz: rotate nightly seeds and add single-seed reproduction
radakam Jun 24, 2026
51921ab
bundle: force-send num_workers for single-node task clusters
radakam Jun 24, 2026
b2c0239
bundle/fuzz: report nightly parity failures and fix create-path comment
radakam Jun 24, 2026
e70783e
bundle/fuzz: make harness files test-only and add num_workers regress…
radakam Jun 24, 2026
a69b574
bundle/fuzz: make the whole package test-only and harden parity repor…
radakam Jun 24, 2026
11dd172
bundle/fuzz: fix lint (stringsseq, testifylint) in paritySeeds
radakam Jun 25, 2026
36e287f
bundle/fuzz: fix nightly issue dedup and document paritySeeds test
radakam Jun 25, 2026
26a29c1
bundle/fuzz: document divergences instead of fixing them
radakam Jun 25, 2026
ae9f26d
bundle/fuzz: narrow num_workers ignore and tidy parity harness
radakam Jun 26, 2026
45cfba6
bundle: force-send num_workers for single-node task clusters
radakam Jun 26, 2026
6cb3060
bundle/fuzz: replace terraform/direct parity with invariant testing
radakam Jun 26, 2026
6325826
acceptance: replace bundle/fuzz parity with schema-driven invariant f…
radakam Jun 29, 2026
ead1515
acceptance/fuzz: clarify comments and tidy schema fuzz harness
radakam Jun 29, 2026
3e106ce
acceptance/fuzz: shorten and tighten comments
radakam Jun 29, 2026
854f00f
acceptance/fuzz: report nightly failures on the PR instead of an issue
radakam Jun 29, 2026
5c9ea27
acceptance/fuzz: reuse the no_drift invariant check instead of duplic…
radakam Jun 29, 2026
2ea9e37
acceptance/fuzz: skip INPUT_CONFIG_OK marker when deploy is rejected
radakam Jun 29, 2026
b4d1a31
acceptance/fuzz: propagate drift failures so the fuzzer detects them
radakam Jun 30, 2026
81fc0bc
acceptance/fuzz: make the fuzzer run any invariant, not just no_drift
radakam Jun 30, 2026
f5a9407
testserver: round-trip catalog create payload fields
radakam Jun 30, 2026
dfd55e2
acceptance/fuzz: add redeploy, canonical, update, destroy_recreate in…
radakam Jun 30, 2026
c663329
acceptance/fuzz: extract shared invariant prologue and tighten comments
radakam Jul 2, 2026
dab9d30
testserver: move catalog round-trip comment above the added fields
radakam Jul 2, 2026
8f9b3fa
Restructure invariant fuzz tests into per-target scripts
radakam Jul 6, 2026
49813ed
invariant: regenerate out.test.toml for volume_path_job_ref
radakam Jul 7, 2026
ba5309a
fuzz: pin catalog/schema references and emit valid grants
radakam Jul 7, 2026
15b4ea7
fuzz: generate multiple resources with cross-references
radakam Jul 7, 2026
565b0d6
fuzz: keep first resource stable across --resource-count
radakam Jul 7, 2026
5b7837f
fuzz: link every resource to an earlier one, not just one pair
radakam Jul 8, 2026
252e16c
invariant: regenerate fuzz out.test.toml for FUZZ_RESOURCE_COUNT=3
radakam Jul 8, 2026
fa5ef1c
fuzz: stage data fixtures and pin typed fields to cut rejections
radakam Jul 10, 2026
2c1ebcd
fuzz: add mutate mode that perturbs curated invariant configs
radakam Jul 10, 2026
b2ddf69
fuzz: probe dangerous and near-range-end values in generate mode
radakam Jul 13, 2026
c333887
acc/fuzz: skip immutable comment/description in update invariant
radakam Jul 13, 2026
e4bac49
acc/fuzz: treat unmodeled testserver routes as rejections, not failures
radakam Jul 13, 2026
c043cd1
acc/fuzz: bound seed execution by time to separate hangs from slow runs
radakam Jul 13, 2026
92e85b1
acc/fuzz: record per-seed classification and a per-variant tally
radakam Jul 13, 2026
927cff4
acc/fuzz: tighten comments added in this PR
radakam Jul 13, 2026
a35eb84
invariant: regenerate out.test.toml for inherited GOOSOnPR and job_ru…
radakam Jul 14, 2026
5e8a03e
acc/fuzz: real oracle, coverage, less rejection waste, clean truncation
radakam Jul 15, 2026
61d1d9c
Ignore root build/ (fuzz coverage + harness terraform artifacts)
radakam Jul 17, 2026
d80a27d
acc/fuzz: pin parent_path to a valid workspace folder
radakam Jul 22, 2026
691ac59
acc/fuzz: regenerate out.test.toml for instance_pool.yml.tmpl
radakam Jul 22, 2026
3a467ca
Remove canonical, update, and destroy_recreate fuzz invariants
radakam Jul 22, 2026
a72e5f9
acc/fuzz: inject valid optional fields in mutate mode
radakam Jul 23, 2026
3b2b189
acc/fuzz: address review — drop dead edit harness, testserver catalog…
radakam Jul 23, 2026
e6d0ec9
acc/fuzz: drop redeploy invariant and multi-resource fuzzing
radakam Jul 24, 2026
c66e0ef
Merge remote-tracking branch 'origin/main' into fuzz-create-payload
radakam Jul 24, 2026
d389ca6
acc/fuzz: fix set -e deploy-code capture, gate validate, guard determ…
radakam Jul 24, 2026
a0612c7
acc/fuzz: rename dispatcher, extract shared prologue, tighten comments
radakam Jul 24, 2026
d134418
acc/fuzz: fix import order after dispatcher rename
radakam Jul 24, 2026
daa3ad0
Merge remote-tracking branch 'origin/main' into fuzz-create-payload
radakam Jul 27, 2026
daca807
acc/fuzz: run the schema fuzzer locally only
radakam Jul 27, 2026
3cff4e5
acc/fuzz: isolate mutate-mode seeds with a per-seed UNIQUE_NAME
radakam Jul 27, 2026
b8576df
acc/invariant: share config render and deploy prologue across all tar…
radakam Jul 27, 2026
a833f00
acc/invariant: trim comments in shared script.prepare
radakam Jul 28, 2026
fc76943
acc/fuzz: make the harness fail when it stops testing anything
radakam Jul 28, 2026
ecc3341
testserver: reject empty catalog and model names like the backend does
radakam Jul 28, 2026
faa212c
acc/invariant: make the shared prologue reusable by generated configs
radakam Jul 28, 2026
67a8b87
acc/invariant: extract the no-drift check into the shared prologue
radakam Jul 28, 2026
4148179
Merge #6075 into fuzz-create-payload and adapt the fuzzer to it
radakam Jul 28, 2026
2714b1a
acc/fuzz: guard INPUT_CONFIG in migrate/script
radakam Jul 28, 2026
057b3b4
acc/fuzz: fuzz the delete and destroy idempotency invariants
radakam Jul 28, 2026
21ba540
acc/fuzz: run the idempotency targets in mutate mode only
radakam Jul 28, 2026
d282604
Merge remote-tracking branch 'origin/main' into fuzz-create-payload
radakam Jul 28, 2026
0782a5c
acc/fuzz: restore errexit in the uncapped seed path
radakam Jul 28, 2026
af4172f
Merge remote-tracking branch 'origin/main' into fuzz-create-payload
radakam Jul 29, 2026
2f6089a
acc/fuzz: run mutate mode on the migrate target
radakam Jul 29, 2026
095f51f
acc/fuzz: trim comments
radakam Jul 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions .github/workflows/push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,72 @@ jobs:
run: |
go tool -modfile=tools/task/go.mod task test-sandbox

test-fuzz:
needs:
- cleanups

# Wide rotating seed window with drift on: too slow for every PR, so nightly only and
# not part of test-result. The committed acceptance test still checks no-panic per PR.
if: ${{ github.event_name == 'schedule' }}
name: "task test-fuzz"
runs-on:
group: databricks-protected-runner-group-large
labels: linux-ubuntu-latest-large

defaults:
run:
shell: bash

permissions:
id-token: write
contents: read
# For the failure-reporting step's PR comment.
pull-requests: write

steps:
- name: Checkout repository and submodules
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Setup build environment
uses: ./.github/actions/setup-build-environment
with:
cache-key: test-fuzz

- name: Run tests
env:
FUZZ_SEED_COUNT: "25"
run: |
# Non-overlapping windows, so CI explores new configs every run.
export FUZZ_SEED_START=$(( GITHUB_RUN_NUMBER * FUZZ_SEED_COUNT ))
go tool -modfile=tools/task/go.mod task test-fuzz

# Not in test-result, so surface failures by commenting on the PR under test.
- name: Report failure
if: ${{ failure() }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
COMMIT: ${{ github.sha }}
run: |
body=$(cat <<EOF
The nightly schema fuzz invariant job (\`task test-fuzz\`) failed while running against
commit \`$COMMIT\`. Each night covers a new seed window, so the failing config is most
likely pre-existing rather than introduced by this commit.

Run: $RUN_URL

The job log prints a ready-to-run repro as \`LOG.repro: fuzz: seed <n> ...\`.
EOF
)

# The commit's pulls endpoint returns the PR that introduced it.
pr=$(gh api "repos/$GITHUB_REPOSITORY/commits/$COMMIT/pulls" --jq '.[0].number // empty')
if [ -n "$pr" ]; then
gh pr comment "$pr" --body "$body"
else
echo "No PR found for commit $COMMIT; skipping failure comment" >&2
fi

# 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.
#
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
*.log
coverage.txt
coverage-acceptance.txt
coverage-fuzz.txt
.coverage

__pycache__
Expand Down
47 changes: 47 additions & 0 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -730,6 +730,53 @@ tasks:
--packages ./acceptance/... \
-- -timeout=${LOCAL_TIMEOUT:-60m} -run "TestAccept/cmd/sandbox"

test-fuzz:
desc: Run schema fuzz invariant tests (random configs, direct engine)
# No `sources:` fingerprint: the window depends on FUZZ_* env vars Task can't see.
cmds:
- |
# Wider window than the committed run, with drift on; a repro narrows it via
# FUZZ_SEED_START/COUNT.
export FUZZ_SEED_COUNT="${FUZZ_SEED_COUNT:-200}"
export FUZZ_CHECK_DRIFT="${FUZZ_CHECK_DRIFT:-1}"
# -count=1: only the script reads FUZZ_*, so the test cache would serve another window's
# result as this one's.
{{.GO_TOOL}} gotestsum \
--format ${GOTESTSUM_FORMAT:-pkgname-and-test-fails} \
--no-summary=skipped \
--packages ./acceptance/... \
-- -count=1 -timeout=${LOCAL_TIMEOUT:-30m} -run "TestAccept/bundle/invariant/fuzz"

test-fuzz-cover:
desc: Run the schema fuzzer under coverage and report which CLI packages it exercises
# No `sources:` fingerprint: like test-fuzz, the window depends on FUZZ_* env vars.
cmds:
- rm -fr ./acceptance/build/cover-fuzz/ ./acceptance/build/cover-fuzz-merged/
- mkdir -p ./acceptance/build/cover-fuzz-merged/
- |
# CLI_GOCOVERDIR makes the harness build a -cover CLI and set GOCOVERDIR per run, so every
# fuzzed `bundle` invocation drops aggregatable counter files. Drift off so the run
# exercises the full deploy/plan path instead of stopping on the first drift.
export CLI_GOCOVERDIR=build/cover-fuzz
export FUZZ_SEED_COUNT="${FUZZ_SEED_COUNT:-100}"
unset FUZZ_CHECK_DRIFT
{{.GO_TOOL}} gotestsum \
--format ${GOTESTSUM_FORMAT:-pkgname-and-test-fails} \
--no-summary=skipped \
--packages ./acceptance/... \
-- -count=1 -timeout=${LOCAL_TIMEOUT:-40m} -run "TestAccept/bundle/invariant/fuzz" || true
- "go tool covdata merge -i $(printf '%s,' acceptance/build/cover-fuzz/* | sed 's/,$//') -o acceptance/build/cover-fuzz-merged/"
- go tool covdata textfmt -i acceptance/build/cover-fuzz-merged -o coverage-fuzz.txt
- |
echo "== total CLI coverage exercised by the fuzz run =="
go tool cover -func=coverage-fuzz.txt | awk '/^total:/{print $NF}'
echo
echo "== bundle/cmd packages by coverage (ascending; 0.0% = never exercised) =="
go tool covdata percent -i=acceptance/build/cover-fuzz-merged \
| awk '/coverage:/{p=$3; gsub(/%/,"",p); sub("github.com/databricks/cli/","",$1); printf "%6.1f%% %s\n", p, $1}' \
| grep -E ' (bundle|cmd/bundle)/' \
| sort -n

# --- Integration tests ---

integration:
Expand Down
71 changes: 71 additions & 0 deletions acceptance/bin/emit_fuzz_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#!/usr/bin/env python3
"""
Emit a fuzz databricks.yml on stdout for the current seed, picking the strategy from FUZZ_MODE so
the invariant scripts don't each duplicate the branch:

generate (default) - build from scratch by walking `bundle schema` (gen_fuzz_config.py).
mutate - perturb a curated invariant config (mutate_fuzz_config.py).

Reads its inputs from the environment the invariant scripts export: FUZZ_SEED, FUZZ_SCHEMA,
UNIQUE_NAME, TESTDIR.
"""

import json
import os
import sys

sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))

from envsubst import substitute_variables
from gen_fuzz_config import gen_config, to_yaml
from mutate_fuzz_config import load_yaml, mutate

# Curated single-resource configs that deploy standalone (only $UNIQUE_NAME, no init script). All
# are in the invariant INPUT_CONFIG matrix, so they stay deploy-verified.
MUTATE_BASES = [
"catalog",
"external_location",
"job",
"model",
"model_serving_endpoint",
"pipeline",
"registered_model",
"schema",
"secret_scope",
"sql_warehouse",
"volume",
]


def generate(seed):
with open(os.environ["FUZZ_SCHEMA"]) as f:
schema = json.load(f)
return to_yaml(gen_config(schema, seed, os.environ["UNIQUE_NAME"]))


def mutate_base(seed):
name = MUTATE_BASES[seed % len(MUTATE_BASES)]
path = os.path.join(os.environ["TESTDIR"], "..", "configs", name + ".yml.tmpl")
unique = os.environ["UNIQUE_NAME"]
with open(path) as f:
rendered = substitute_variables(f.read())
config = load_yaml(rendered)
# The schema lets mutate inject valid optional fields, not just perturb existing ones.
with open(os.environ["FUZZ_SCHEMA"]) as f:
schema = json.load(f)
return to_yaml(mutate(config, seed, schema=schema, unique=unique))


def main():
seed = int(os.environ["FUZZ_SEED"])
mode = os.environ.get("FUZZ_MODE", "generate")
if mode == "generate":
sys.stdout.write(generate(seed))
elif mode == "mutate":
sys.stdout.write(mutate_base(seed))
else:
sys.exit(f"emit_fuzz_config: unknown FUZZ_MODE {mode!r}")


if __name__ == "__main__":
main()
Loading
Loading