Skip to content

feat(cli): add lakebench CLI (run/results/report/discover/doctor/profiles)#85

Draft
tomz wants to merge 3 commits into
microsoft:mainfrom
tomz:pr3-cli
Draft

feat(cli): add lakebench CLI (run/results/report/discover/doctor/profiles)#85
tomz wants to merge 3 commits into
microsoft:mainfrom
tomz:pr3-cli

Conversation

@tomz
Copy link
Copy Markdown

@tomz tomz commented May 29, 2026

Part 3/5 of a stack: #1 (lint) → #2 (cloud engines) → #3 (cli)#4 (tpcdi) → #5 (databricks). Best reviewed in order; each builds on the previous.

What

Adds a lakebench command-line interface and supporting config/results/reporting plumbing.

  • Subcommands: run, results, report, discover, doctor, profiles.
  • Profile-based engine configuration in config.py.
  • CLI formatting/override helpers, results + reporting modules.
  • Docs: CLI quickstart, CLI reference, architecture, development.

Fix included: token_env credential-dropping bug

config.resolve_engine previously stripped *_env suffixes to bare keys (token_envtoken) and then dropped them in the signature filter — so credentials configured via env-var profiles never reached the engine, silently breaking the documented Databricks/Livy profile flow.

resolve_engine now inspects the engine __init__ signature: it passes the env-var name through untouched when the engine accepts a *_env parameter (Databricks/Livy), and resolves to the value for bare-key / **kwargs engines.

Tests

New tests/test_config.py (11 tests) covering the env-var resolution paths, plus CLI tests. Suite green (172 passed, 2 skipped).

tomz added 3 commits May 29, 2026 12:32
Add a conservative ruff config (E/F/I/W), a pre-commit hook set, and a CI
lint job (lint + format both enforcing). Reformat the existing tree with
`ruff format` and replace ad-hoc print() diagnostics with module-level
loggers across datagen and timing helpers. Fix obvious nits surfaced by ruff
(import order, bare except -> except Exception, dead assignment).

Drop Python 3.8 support and move pyarrow to base dependencies (the core
results/timing modules import it unconditionally). Gitignore scratch/ for
workspace-specific scratchpads.

W291/W293 stay globally ignored because trailing whitespace inside multi-line
SQL string literals is intentional and not touched by `ruff format`.
Add remote/cloud engines that talk to managed Spark via protocol:

- Livy   — Fabric / Synapse / HDInsight via the Livy REST API, with
           session auto-recovery, per-query timeout, multi-part SHOW TABLES.
- SparkConnect — Spark Connect gRPC client.
- FabricSpark / SynapseSpark / HDISpark — workspace-tagged Spark subclasses.

Catalog plumbing shared by all engines:
- BaseEngine.list_databases() / list_tables() / get_table_columns() defaults,
  overridden for the Spark family, Livy and DuckDB.
- query_timeout_seconds attribute.
- transpile_and_qualify_query() rewritten with AST-based qualification that
  correctly handles 3-/4-part names (workspace.lakehouse.schema, Unity
  catalog.schema): builds quoted identifier chains via sqlglot, preserves the
  caller's catalog, and leaves CTE references untouched. Adds 9 multi-part
  tests (previously untested).

Column auto-remap is opt-in (auto_remap_columns=False) and warns loudly when
active — silently rewriting columns to match non-spec data hurts benchmark
reproducibility and can mask data-prep bugs.

Register Livy as a generic engine for TPC-H / TPC-DS / ClickBench.
…iles)

A purely additive command-line surface over the existing Python API.
Library consumers are unaffected.

- cli/ package: argparse plumbing, override merge (-E/--conf), output
  formatting (human/table/json/csv/yaml), dry-run/print-config, verbosity
  and meaningful exit codes.
- config.py: profile loader (~/.lakebench.json + ./lakebench.json), env-var
  expansion, `extends:` composition, validation, lazy engine/benchmark
  registries.

  resolve_engine() handles *_env credential references by honoring the engine
  signature: engines that accept the env-var NAME (Databricks, Livy) get it
  untouched and resolve the secret themselves; engines that accept the bare
  key (or **kwargs) get the resolved value. This avoids silently dropping the
  credential. Covered by tests/test_config.py.
- results.py / reporting.py / discover.py as before.
- Expose console_script entry point and livy/spark_connect extras + Fabric/
  Synapse/HDInsight aliases.

Docs: cli-quickstart, cli-reference, architecture, development.
@tomz
Copy link
Copy Markdown
Author

tomz commented May 29, 2026

Part 3/5 of the stack in #82, following #84. Diff note: targets main (fork-only branches), so the diff currently includes #83+#84; it narrows to just the CLI work after those merge and I rebase. Merge order: #83#84#85#86#87.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant