From 0ae1e4aefbfcbd3d05a8ed970cdd60b374ad74e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peer=20Gr=C3=B8nnerup?= Date: Tue, 27 Oct 2026 19:57:15 +0100 Subject: [PATCH] Document te CLI 0.8.0 - Add te schemacheck to the command reference: options, findings and codes, exit rule, checked and not-checked tables, TE2 annotations, JSON and TRX output. Supersedes #430. - Add te schemacheck to the overview, automation, findings JSON and CI/CD pages, and to the TE2 Command-line Options page - Migrate: map -SC to te schemacheck, add a Schema check section on te2 -SC vs te schemacheck, and document the TE2 compatibility mode script changes (a failed script stops the run, compile errors show their location, one batch per script, TECLI defined) - Limitations: add a Schema check section - Document the renamed --save options: te test snapshot -o/--output-file, te vertipaq --annotate --push, and --auth env instead of te auth login --save=false - Add te deploy --skip-linguistic-metadata - Note BlockUnsafeScripts on te script, the 80-character M line width, and the per-object TMDL folder layout - Remove te test run --fail-on, which no longer exists - Move the preview end date to 2026-12-31 --- content/features/Command-line-Options.md | 2 + .../te-cli/includes/te-cli-preview-notice.md | 2 +- content/features/te-cli/te-cli-auth.md | 4 +- content/features/te-cli/te-cli-automation.md | 6 +- content/features/te-cli/te-cli-cicd.md | 22 ++++- content/features/te-cli/te-cli-commands.md | 92 +++++++++++++++++-- content/features/te-cli/te-cli-findings.md | 13 +-- content/features/te-cli/te-cli-install.md | 4 +- content/features/te-cli/te-cli-limitations.md | 11 ++- content/features/te-cli/te-cli-migrate.md | 33 ++++++- content/features/te-cli/te-cli.md | 6 +- 11 files changed, 160 insertions(+), 35 deletions(-) diff --git a/content/features/Command-line-Options.md b/content/features/Command-line-Options.md index c2148da28..cab22381f 100644 --- a/content/features/Command-line-Options.md +++ b/content/features/Command-line-Options.md @@ -366,6 +366,8 @@ As of [version 2.8](https://github.com/TabularEditor/TabularEditor/releases/tag/ You can also annotate tables and columns if you want the schema check to treat them in a specific way. [More information here](xref:importing-tables-te2#ignoring-objects). +The Tabular Editor CLI runs the same check with [`te schemacheck`](xref:te-cli-commands#schemacheck), which also checks Power Query (M) and Direct Lake tables. + ## Command Line output and Exit Codes The command line provides various details, depending on the switches used and any events encountered during execution. Exit Codes were introduced in [version 2.7.4](https://github.com/TabularEditor/TabularEditor/releases/tag/2.7.4). diff --git a/content/features/te-cli/includes/te-cli-preview-notice.md b/content/features/te-cli/includes/te-cli-preview-notice.md index e9dbcc25c..ff879adac 100644 --- a/content/features/te-cli/includes/te-cli-preview-notice.md +++ b/content/features/te-cli/includes/te-cli-preview-notice.md @@ -1,2 +1,2 @@ > [!IMPORTANT] -> The Tabular Editor CLI is in **Limited Public Preview**. It is offered for evaluation with a Tabular Editor account; no license is required during preview. Commands, flags, and outputs may change before general availability. **The preview build stops functioning after 2026-10-31.** We recommend against using the CLI in production CI/CD pipelines during preview. +> The Tabular Editor CLI is in **Limited Public Preview**. It is offered for evaluation with a Tabular Editor account; no license is required during preview. Commands, flags, and outputs may change before general availability. **The preview build stops functioning after 2026-12-31.** We recommend against using the CLI in production CI/CD pipelines during preview. diff --git a/content/features/te-cli/te-cli-auth.md b/content/features/te-cli/te-cli-auth.md index 3348d29f2..44727aba7 100644 --- a/content/features/te-cli/te-cli-auth.md +++ b/content/features/te-cli/te-cli-auth.md @@ -2,7 +2,7 @@ uid: te-cli-auth title: Authentication and Connections author: Peer Grønnerup -updated: 2026-09-11 +updated: 2026-10-27 applies_to: products: - product: Tabular Editor 2 @@ -60,7 +60,7 @@ te auth login -u "$AZURE_CLIENT_ID" -t "$AZURE_TENANT_ID" --certificate ./sp.pfx te auth login --identity # Alias: -I ``` -After a successful service-principal login the CLI **caches the credentials** so every subsequent `te` command can acquire tokens silently - no need to re-pass `-u / -p / -t` or set the `AZURE_CLIENT_*` environment variables. Pass `--save=false` for a one-shot login that doesn't update the cache, or run `te auth logout` to clear it. +After a successful service-principal login the CLI **caches the credentials** so every subsequent `te` command can acquire tokens silently - no need to re-pass `-u / -p / -t` or set the `AZURE_CLIENT_*` environment variables. Run `te auth logout` to clear the cache. To use a service principal without storing its credentials on the machine, skip `te auth login`: set `AZURE_CLIENT_ID`, `AZURE_CLIENT_SECRET` and `AZURE_TENANT_ID` and pass `--auth env` to each command. > [!WARNING] > Passing secrets directly on the command line exposes them to process listings and shell history. Prefer the `AZURE_CLIENT_SECRET` environment variable, or pipe the secret via stdin with `-p -`. diff --git a/content/features/te-cli/te-cli-automation.md b/content/features/te-cli/te-cli-automation.md index f67dfbba4..fa0d3782a 100644 --- a/content/features/te-cli/te-cli-automation.md +++ b/content/features/te-cli/te-cli-automation.md @@ -2,7 +2,7 @@ uid: te-cli-automation title: Automation and Scripting author: Peer Grønnerup -updated: 2026-09-11 +updated: 2026-10-27 applies_to: products: - product: Tabular Editor 2 @@ -36,7 +36,7 @@ te query -q "EVALUATE VALUES('Date'[Year])" --output-format csv te bpa run --output-format json ``` -Under `--output-format json`, `te validate`, `te bpa run`, `te test run`, and `te query` share one JSON document shape with a `summary`, a flat `findings[]` array, and `durationMs` - see @te-cli-findings for the shape to parse. +Under `--output-format json`, `te validate`, `te bpa run`, `te schemacheck`, `te test run`, and `te query` share one JSON document shape with a `summary`, a flat `findings[]` array, and `durationMs` - see @te-cli-findings for the shape to parse. > [!NOTE] > `--output-format` and `--error-format` are independent. Setting `--output-format json` does *not* switch stderr to JSON; pass `--error-format json` for that. There is no automatic format switching when stdout is redirected - the default is always `text` unless you ask otherwise. @@ -59,7 +59,7 @@ Every `te` command exits with a predictable status code so callers can branch on | Exit | Meaning | | -- | -- | | `0` | Success. | -| `1` | Generic failure - invalid arguments, command failed, validation errors, auth failure, BPA gate failed at severity >= error, a `te script` run in which a script called `Error(...)`, a `te deploy` the server accepted with object errors. For `te diff`: differences found (like the `diff`/`cmp` convention). | +| `1` | Generic failure - invalid arguments, command failed, validation errors, auth failure, BPA gate failed at severity >= error, a `te schemacheck` run that found an error (or any drift with `--fail-on warning`), a `te script` run in which a script called `Error(...)`, a `te deploy` the server accepted with object errors. For `te diff`: differences found (like the `diff`/`cmp` convention). | | `2` | `te diff` only: an error occurred while comparing, so the difference status is unknown. | Combine exit codes with `--ci ` annotations and `--trx ` to surface rich failure information in CI - see @te-cli-cicd. diff --git a/content/features/te-cli/te-cli-cicd.md b/content/features/te-cli/te-cli-cicd.md index af1939b97..a36ea1c3b 100644 --- a/content/features/te-cli/te-cli-cicd.md +++ b/content/features/te-cli/te-cli-cicd.md @@ -2,7 +2,7 @@ uid: te-cli-cicd title: CI/CD Integration author: Peer Grønnerup -updated: 2026-09-11 +updated: 2026-10-27 applies_to: products: - product: Tabular Editor 2 @@ -21,7 +21,7 @@ The Tabular Editor CLI is designed for unattended execution in continuous integr > [!WARNING] > **Do not use the CLI in production pipelines during Limited Public Preview.** Two preview-specific risks apply to pipeline owners: > -> - **Hard expiry.** The preview binary stops functioning on **2026-10-31** - any pipeline depending on it will fail on that date, regardless of your release calendar. +> - **Hard expiry.** The preview binary stops functioning on **2026-12-31** - any pipeline depending on it will fail on that date, regardless of your release calendar. > - **No backwards-compatibility guarantee.** Commands, flags, output shapes, and exit codes may change between preview builds, so pipeline steps may need updating when you refresh the vendored binary. > > Build and evaluate in non-production pipelines, and share feedback in the public [TabularEditor/CLI](https://github.com/TabularEditor/CLI) repository so the GA version matches your needs. @@ -35,7 +35,7 @@ The Tabular Editor CLI is designed for unattended execution in continuous integr - **`--ci vsts` / `--ci github`.** Emit native pipeline annotations to stderr, carrying the finding's code (`code=` on Azure DevOps, `title=` on GitHub). `azdo` / `azure-devops` and `gh` are accepted aliases, `none` means no annotations, and a mistyped value is rejected before the command runs instead of silently emitting nothing. - **`--trx `.** Produce VSTEST results consumable by Azure DevOps test publishing. - **Structured errors.** `--error-format json` emits `{"error": "...", "hint": "..."}` to stderr so pipeline steps can fail with a useful message. -- **One findings JSON.** `te validate`, `te bpa run`, `te test run`, and `te query` share a single machine-readable JSON document under `--output-format json` - a `summary`, a flat `findings[]` array with `severity`/`source`/`code`/`message`, and, where resolvable, an `objectPath` you can feed back to `te get`. See @te-cli-findings. +- **One findings JSON.** `te validate`, `te bpa run`, `te schemacheck`, `te test run`, and `te query` share a single machine-readable JSON document under `--output-format json` - a `summary`, a flat `findings[]` array with `severity`/`source`/`code`/`message`, and, where resolvable, an `objectPath` you can feed back to `te get`. See @te-cli-findings. ## Adding the CLI to your repo @@ -54,7 +54,7 @@ your-repo/ Place the **extracted** binary - not the archive - so the pipeline can call it directly. Pick the build that matches your runner OS/arch; see @te-cli-install for the filename table. The self-contained binary is ~70 MB; consider Git LFS if your repo is sensitive to size. > [!NOTE] -> Committing the binary also pins the CLI version to whatever you checked in, which is desirable for CI reproducibility. To upgrade, replace the binary in `tools/te/` and commit it - the commit message is your version log. Keep in mind that the preview binary still expires on **2026-10-31** regardless of when you committed it, so a vendored copy is not a permanent dependency - plan to refresh it (and re-validate your pipeline against the new API surface) on preview-build cadence. +> Committing the binary also pins the CLI version to whatever you checked in, which is desirable for CI reproducibility. To upgrade, replace the binary in `tools/te/` and commit it - the commit message is your version log. Keep in mind that the preview binary still expires on **2026-12-31** regardless of when you committed it, so a vendored copy is not a permanent dependency - plan to refresh it (and re-validate your pipeline against the new API surface) on preview-build cadence. ## GitHub Actions @@ -186,6 +186,20 @@ te deploy --model ./model --target-server my-ws --target-database my-model --ski See @te-cli-config for controlling the BPA gate globally via `bpa.onDeploy` / `bpa.onSave` config keys. +## Schema drift check + +Run [`te schemacheck`](xref:te-cli-commands#schemacheck) before a deploy to catch source columns that were dropped or retyped since the model was last updated. The agent needs network access and credentials for the model's data sources. + +```bash +# A missing source column fails the step; added or retyped columns are warnings +te schemacheck --model ./model --non-interactive --ci vsts --trx schema.trx + +# Fail on any drift +te schemacheck --model ./model --non-interactive --fail-on warning --ci github +``` + +Tables the CLI can't check are listed with the reason and don't fail the step. To fail on them too, check `tablesSkipped` in the JSON output. + ## Script validation C# scripts can be compile-checked without loading any model - an offline lint step for PR validation: diff --git a/content/features/te-cli/te-cli-commands.md b/content/features/te-cli/te-cli-commands.md index 3e0f0ae6f..d8118eb27 100644 --- a/content/features/te-cli/te-cli-commands.md +++ b/content/features/te-cli/te-cli-commands.md @@ -2,7 +2,7 @@ uid: te-cli-commands title: Command Reference author: Peer Grønnerup -updated: 2026-09-11 +updated: 2026-10-27 applies_to: products: - product: Tabular Editor 2 @@ -196,6 +196,8 @@ te save-as -o ./project --serialization pbip # Save as a PBIP project te save-as -o ./out -s my-workspace -d my-model --skip-validation # Fast download ``` +A TMDL folder can be saved with one file per object (column, measure, partition, and so on) instead of one file per table. That choice is stored in the folder, and `te` keeps whatever layout a folder already has; you choose the layout in Tabular Editor 3. When a save writes the standard layout over a folder that used one file per object, `te` prints a warning. + `--serialization pbip` output opens directly in Power BI Desktop and is named after the source model (`SpaceParts.pbip`, not `Model.pbip`). Saving into a folder that already holds a project adds only the files that are missing and leaves everything already there - the report's pages, theme, connection, and item identity - exactly as it was, so a save that changes nothing leaves the project unchanged under source control. Validation guards saving: a model with a name collision Analysis Services would refuse (`TE0012` / `TE0013`, see [validate](#validate)) is not written unless `--force` or `--skip-validation` is passed. @@ -513,7 +515,7 @@ te validate --errors-only # Hide warnings and anti-pattern hints Every finding carries a stable code, shown in the **Code** column of the Errors, Warnings, and Anti-patterns tables as well as in JSON, `--ci` annotations, and `--trx`. Three codes are worth knowing when a hand-written model is involved: `TE0012` (a column and a measure, or two columns, share a name within one table) and `TE0013` (a measure name is repeated across tables) are errors - Analysis Services refuses to load such a model, and `te save-as` refuses to write one unless `--force` or `--skip-validation` is passed; `TE0014` is a warning that a TMDL folder has no `database.tmdl`, so the compatibility level in effect is a substitute for the one the model declared. The folder still loads and `te validate` still exits `0` for `TE0014`; hide it like any other warning with `--no-warnings` or `--errors-only`. -Under `--output-format json`, `te validate` emits the shared findings JSON document (`summary` plus a flat `findings[]` array) shared with `te bpa run`, `te test run`, and `te query` - see @te-cli-findings. +Under `--output-format json`, `te validate` emits the shared findings JSON document (`summary` plus a flat `findings[]` array) shared with `te bpa run`, `te schemacheck`, `te test run`, and `te query` - see @te-cli-findings. > [!NOTE] > `te validate` does not support `--output-format csv` - CSV is rejected up front with an actionable error rather than producing a partial result. Use `text` or `json` for validation output. @@ -692,6 +694,72 @@ Re-enable a previously disabled built-in BPA rule by removing the rule ID from ` te bpa rules enable TE3_BUILT_IN_DATE_TABLE_EXISTS ``` +### schemacheck + +Compare each table in the model with the data source it reads from, and report columns that no longer match. `te schemacheck` never changes the model. To apply what it finds, use [`te set --update-schema`](#set). It replaces the `-SC` flag of Tabular Editor 2; see [Schema check](xref:te-cli-migrate#schema-check) for the differences. + +`te schemacheck` accepts: + +- `
` - optional: check one table. Without it, every table in the model is checked. +- `--fail-on ` - `error` (default) or `warning`. With `warning`, any drift fails the run. +- `--ci ` - emit CI annotations to stderr: `vsts` (aliases `azdo`, `azure-devops`) or `github` (alias `gh`). +- `--trx ` - write a VSTEST `.trx` file with one result per finding. +- `--source`, `--endpoint`, `--connection-string`, `--source-database`, `--source-table` - for a single table, read the schema from somewhere else. These are the same flags as on [`te add -t Table`](#add). `--source-table` on its own changes only the name of the source table, and keeps the connection. + +You don't need to name a connection: each table is compared with the data source its partitions are bound to. The machine running `te` needs network access and credentials for those data sources. + +```bash +te schemacheck # Check every table +te schemacheck Sales # Check one table +te schemacheck --fail-on warning # Fail on any drift +te schemacheck --ci vsts --trx schema.trx # Azure DevOps annotations and test results +te schemacheck Sales --source-table dbo.fact_sales # Compare Sales with another source table +``` + +#### What it reports + +| Finding | Code | Severity | +| -- | -- | -- | +| A source column that no column in the table reads. | `SCHEMA_SOURCE_COLUMN_ADDED` | Warning | +| A column whose data type differs from its source column. | `SCHEMA_DATA_TYPE_CHANGED` | Warning | +| A column whose source column no longer exists. | `SCHEMA_MISSING_SOURCE_COLUMN` | Error | +| A legacy SQL query partition whose query can't be read, for example because it's blank or the server can't be reached. | `SCHEMA_SOURCE_QUERY_ERROR` | Error | +| The source returns the same column name more than once. Only the first is compared. | `SCHEMA_DUPLICATE_SOURCE_COLUMN` | Info | +| The table was not checked. The message says why. | `SCHEMA_TABLE_SKIPPED` | Info | + +An error exits with code `1`, and a warning exits with code `0` unless you pass `--fail-on warning`. This is the rule Tabular Editor 2 used, so a migrated pipeline keeps the result it has today. With `--ci vsts`, a run with only warnings reports **SucceededWithIssues**. + +A renamed source column is reported as one missing column and one added column. Point the model column at the new name with `te set
/ -p SourceColumn=`, which keeps the column's properties and the DAX that refers to it. + +#### What it checks + +`te schemacheck` checks tables with legacy SQL query partitions, tables with Power Query (M) partitions, and Direct Lake or Fabric tables. These tables are listed under **Not checked**, with the reason, and never fail the run: + +- calculated tables and calculation groups +- tables with the `TabularEditor_SkipSchemaCheck` annotation +- tables with no column bound to a source column +- tables on a source the CLI can't read, such as Oracle, ODBC, SharePoint, or a Power Query expression it can't follow + +Legacy partitions on the SQL Server OLE DB providers (`SQLOLEDB` and `MSOLEDBSQL`) can only be checked on Windows. On Linux and macOS, such a table is reported as an error. + +#### Annotations + +`te schemacheck` honors the schema check annotations from Tabular Editor 2, described in [Ignoring objects](xref:importing-tables-te2#ignoring-objects): + +- `TabularEditor_SkipSchemaCheck` on a table skips it. The misspelled `TabularEditor_SkipSkemaCheck` also works. +- `TabularEditor_IgnoreSourceColumnAdded` on a table hides added source columns. +- `TabularEditor_IgnoreDataTypeChange` on a table or a column hides data type changes. +- `TabularEditor_IgnoreMissingSourceColumn` on a table or a column hides missing source columns. +- `TabularEditor_SchemaCheckNoWarnings` on the model turns every warning into an error, so any drift fails every run. `--fail-on warning` does the same for a single run. + +`TabularEditor_AddFalseWhereClause` is ignored, as in Tabular Editor 3: the query is sent as written. + +#### Output + +Text and JSON output are supported. Under `--output-format json`, `te schemacheck` emits the shared findings JSON document with three extra counts: `tablesChecked`, `tablesSkipped` and `tablesWithDrift` - see @te-cli-findings. + +The `--trx` file has one result per finding under the **Schema Checks** suite: failed for an error, warning for a warning, and inconclusive for a table that was not checked. A run without drift writes a single passed result. + ### vertipaq Analyze VertiPaq storage statistics. @@ -705,7 +773,9 @@ Analyze VertiPaq storage statistics. - `--export ` - export VertiPaq stats to a `.vpax` file for offline analysis. - `--import ` - load a previously exported `.vpax` file and analyze it offline. - `--obfuscate` - obfuscate names and expressions in exported VPAX. -- `--top `, `--stats`, `--annotate`, `--save`. +- `--top `, `--stats`. +- `--annotate` - prepare the statistics as annotations on each table and column (size, cardinality and so on). On its own it only reports what it would write. +- `--push` - write the annotations prepared by `--annotate` to the model on the server. Requires `--annotate`, and can't be combined with `--import`. - `--auth ` - auth method override when connecting to a remote model. ```bash @@ -714,6 +784,7 @@ te vertipaq Sales # Stats limited to the Sales table te vertipaq --all # Tables, columns, relationships, partitions te vertipaq --export stats.vpax te vertipaq --import stats.vpax # Analyze offline +te vertipaq --annotate --push # Write the statistics to the model as annotations ``` ### Formatting expressions @@ -771,7 +842,7 @@ echo "Info(Model.Name);" | te script --inline - te script --file fix.cs --validate # Compile-only, no model needed ``` -A run in which any script calls `Error(...)` exits non-zero, reports `"success": false` in JSON, and closes by saying the run completed with errors; changes the script already made are still saved when `--save` is given. `Warning(...)` and `Info(...)` never fail a run. On Windows, the `DisableCSharpScripts` administrator policy refuses `te script` outright - see [Administrator policies](xref:te-cli-config#administrator-policies). +A run in which any script calls `Error(...)` exits non-zero, reports `"success": false` in JSON, and closes by saying the run completed with errors; changes the script already made are still saved when `--save` is given. `Warning(...)` and `Info(...)` never fail a run. On Windows, the `DisableCSharpScripts` administrator policy refuses `te script` outright, and `BlockUnsafeScripts` refuses a script that reaches outside the model, for example to read a file or call a web service - see [Administrator policies](xref:te-cli-config#administrator-policies). > [!IMPORTANT] > Two behavioral details to know if you're porting an older script: @@ -883,6 +954,7 @@ Deploy a semantic model to Power BI, Fabric, Azure Analysis Services, or on-prem - `--deploy-role-members` - `--deploy-shared-expressions` - `--create-only` +- `--skip-linguistic-metadata` - keep the target model's AI instructions, AI data schema and Q&A synonyms instead of replacing them with the model's own. Use it when someone maintains these in the Power BI service with **Prep data for AI**. Also applies with `--deploy-full`. - `--skip-bpa` - bypass the BPA gate entirely. - `--fix-bpa` - auto-fix BPA violations where rules define a fix expression. - `--bpa-rules ` - repeatable; override `bpa.rules` from your CLI config for this single deploy. Built-in rules still apply unless `bpa.builtInRules` is `false`. @@ -898,6 +970,7 @@ te deploy -m ./model --target-server MY.SERVER.COM --target-database my-model -- te deploy -m ./model --target-server my-workspace --target-database my-model > deploy.tmsl # Dry run: TMSL only te deploy -s src-workspace -d src-model --target-server dst-workspace --target-database copy --execute # Remote to remote te deploy --local --target-server my-workspace --target-database my-model --execute # Publish a Desktop model +te deploy -m ./model --target-server my-workspace --target-database my-model --skip-linguistic-metadata --execute # Keep the AI instructions set up in the service ``` > [!IMPORTANT] @@ -948,7 +1021,6 @@ Run a suite of DAX assertion tests against a deployed model. - `--suite ` - test-suite directory (default: `.te-tests/`). - `--tag ` - only tests with this tag. -- `--fail-on ` - `error` (default) or `warning`. - `--ci `, `--trx ` - CI annotations and TRX output. ```bash @@ -968,8 +1040,12 @@ Additional subcommands scaffold tests, print the assertion spec format, switch t te test init --example # Scaffold an example suite te test spec # Print the full assertion format reference te test init --from-model --model ./my-model # Generate stubs from your measures +te test snapshot -o baseline.json # Capture every measure's value +te test snapshot --diff baseline.json # Compare against the baseline ``` +`te test snapshot` writes the snapshot to the file named by `-o, --output-file`, or compares against a baseline with `--diff `; one of the two is required. + ## Connection and authentication ### connect @@ -1053,7 +1129,7 @@ JSON output carries `success`, `formatted`, and `errors`. For expressions alread ### util format-m -Format a loose M/Power Query expression. `-` reads from stdin; no language-specific options. A malformed expression - an unterminated string, for example - is reported as a failure with a non-zero exit code and the original text returned unchanged, never a silently shortened result. +Format a loose M/Power Query expression. `-` reads from stdin; no language-specific options. Lines are wrapped at 80 characters, the same as `te set --format` uses for M. A malformed expression - an unterminated string, for example - is reported as a failure with a non-zero exit code and the original text returned unchanged, never a silently shortened result. ```bash te util format-m "let x = 1 in x" @@ -1139,7 +1215,7 @@ te completion fish | Exit | Meaning | | -- | -- | | `0` | Success. | -| `1` | Generic failure (invalid arguments, command failed, validation errors, auth failure, BPA gate failed at severity >= error, a `te script` run in which a script reported an error, a `te deploy` the server accepted with object errors). For `te diff`: differences found. | +| `1` | Generic failure (invalid arguments, command failed, validation errors, auth failure, BPA gate failed at severity >= error, a `te schemacheck` run that found an error (or any drift with `--fail-on warning`), a `te script` run in which a script reported an error, a `te deploy` the server accepted with object errors). For `te diff`: differences found. | | `2` | `te diff` only: an error occurred while comparing, so the difference status is unknown. | For fine-grained control in CI pipelines, combine exit codes with `--ci ` annotations and `--trx` results files - see @te-cli-cicd. @@ -1150,5 +1226,5 @@ For fine-grained control in CI pipelines, combine exit codes with `--ci [!NOTE] > `te query` uses this JSON shape only when its pre-execution DAX validation produces at least one error. A successful query emits the query result instead: `{columns, rows, rowCount, truncated, durationMs, trace?}`. @@ -57,8 +57,8 @@ Present on **every** finding: | Key | Values / meaning | | -- | -- | | `severity` | `error`, `warning`, or `info`. | -| `source` | `validate`, `bpa`, `test`, or `query`. | -| `code` | Stable finding code (a validation message ID, BPA rule ID, `TEST_FAIL` / `TEST_ERROR` / `TEST_SUITE_INVALID`, ...). | +| `source` | `validate`, `bpa`, `schemaCheck`, `test`, or `query`. | +| `code` | Stable finding code (a validation message ID, BPA rule ID, `TEST_FAIL` / `TEST_ERROR` / `TEST_SUITE_INVALID`, a [schema check code](xref:te-cli-commands#what-it-reports), ...). | | `message` | Human-readable description. | | `object` | Bare name of the object the finding is about. | | `objectType` | One of a closed vocabulary - see below. | @@ -68,7 +68,7 @@ Present **only where the CLI knows them** - these keys are *absent* rather than | Key | Populated by | Meaning | | -- | -- | -- | -| `objectPath` | `validate` and `bpa` violations only | Canonical object path, resolvable as-is by `te get` or `te set`. Absent for test findings, query findings, and BPA rule errors. | +| `objectPath` | `validate`, `bpa` violations and `schemaCheck` | Canonical object path, resolvable as-is by `te get` or `te set`. Absent for test findings, query findings, and BPA rule errors. | | `expressionPosition` | `validate` and `query` only | `{property, lineNumber, column}` inside the named expression property. **Optional on every source, including validate and query** - absent whenever the analyzer reported no usable position, and all-or-nothing (never a partial position). | | `ruleName`, `category` | `bpa` only | The violated rule's name and category. | @@ -87,12 +87,13 @@ Each command keeps a few keys of its own at the top level of the document: | `te validate` | `valid` (boolean). | | `te bpa run` | `model`, `rulesEvaluated`, `violations`, `ruleErrors`, `ignoredRules`. Rule-evaluation errors appear in `findings` at severity `error` with `objectType: "BpaRule"` - `violations` and `ruleErrors` split the two counts. | | `te bpa run --fix` | A `fix` key inside the same single document: `changes`, `fixed`, `fixErrors`, `skipped`, `fixedItems`, `fixErrorItems`. If the fix pass itself fails, the document is still written with the reason in `fix.error`. Absent without `--fix`. | +| `te schemacheck` | `tablesChecked`, `tablesSkipped`, `tablesWithDrift`. Each table that was not checked is also an `info` finding with code `SCHEMA_TABLE_SKIPPED`. | | `te test run` | `suites`, `invalidSuites`, `testSummary` (per-status test tallies; `summary` remains the shared severity tally). | | `te query` | None - and only on validation errors; see the note above. | ## CI annotations -All four commands share one annotation writer for `--ci vsts` / `--ci github` (`azdo`, `azure-devops`, and `gh` are accepted aliases; `none` disables annotations; anything else is rejected before the command runs). Annotations go to stderr; stdout stays parseable: +All five commands share one annotation writer for `--ci vsts` / `--ci github` (`azdo`, `azure-devops`, and `gh` are accepted aliases; `none` disables annotations; anything else is rejected before the command runs). Annotations go to stderr; stdout stays parseable: - Annotations carry the finding's code: `code=` on Azure DevOps, `title=` on GitHub. - Info-severity findings are not warnings: on GitHub they emit `::notice::`, on Azure DevOps a plain log line. An Azure DevOps run whose only findings are informational reports **Succeeded**. diff --git a/content/features/te-cli/te-cli-install.md b/content/features/te-cli/te-cli-install.md index 7e2c09d12..fe07ad466 100644 --- a/content/features/te-cli/te-cli-install.md +++ b/content/features/te-cli/te-cli-install.md @@ -2,7 +2,7 @@ uid: te-cli-install title: Installation and Setup author: Peer Grønnerup -updated: 2026-09-04 +updated: 2026-10-27 applies_to: products: - product: Tabular Editor 2 @@ -127,7 +127,7 @@ te config set hidePreviewNotice true ``` > [!WARNING] -> The banner reappears on every command within **14 days of the preview end date** (2026-10-31), regardless of `hidePreviewNotice`. This ensures you have visible warning before the CLI stops functioning. +> The banner reappears on every command within **14 days of the preview end date** (2026-12-31), regardless of `hidePreviewNotice`. This ensures you have visible warning before the CLI stops functioning. ## Shell completion diff --git a/content/features/te-cli/te-cli-limitations.md b/content/features/te-cli/te-cli-limitations.md index 11470df38..37b8fa52a 100644 --- a/content/features/te-cli/te-cli-limitations.md +++ b/content/features/te-cli/te-cli-limitations.md @@ -2,7 +2,7 @@ uid: te-cli-limitations title: Behavior Differences and Known Limitations author: Peer Grønnerup -updated: 2026-09-11 +updated: 2026-10-27 applies_to: products: - product: Tabular Editor 2 @@ -53,6 +53,15 @@ The CLI runs C# scripts (`te script`) against the same `Model` object you use in | -- | -- | | **`te validate` cannot auto-fix Code Action violations** | `te validate` reports Code Action violations but offers no CLI flag to apply the suggested fix. Apply the fix in Tabular Editor 3, or use `te bpa run --fix` for the subset of Code Actions that overlap with BPA rules. | +## Schema check + +| Limitation | Notes / Workaround | +| -- | -- | +| **Oracle, ODBC and other OLE DB sources are not checked** | Tabular Editor 2's `-SC` checked legacy query partitions on these sources. [`te schemacheck`](xref:te-cli-commands#schemacheck) and `te2 -SC` list such a table under **Not checked**, and it doesn't fail the run. The SQL Server OLE DB providers are still checked. | +| **OLE DB sources can only be checked on Windows** | Legacy partitions on `SQLOLEDB` or `MSOLEDBSQL` are reported as an error on Linux and macOS. Run the schema check on a Windows agent. | +| **The single-table override reads SQL Server and Fabric only** | `te schemacheck
` with `--source`, `--connection-string` or `--source-table` reads SQL Server, Azure SQL, and Fabric Lakehouse and Warehouse SQL endpoints. A table on any other source is refused. Run without the override flags to check it against its own data source. | +| **Renamed source columns are reported as missing + added** | Matching is by name, so a rename can't be detected. Remap the column with `te set
/ -p SourceColumn=`. | + ## Model initialization and save | Limitation | Notes / Workaround | diff --git a/content/features/te-cli/te-cli-migrate.md b/content/features/te-cli/te-cli-migrate.md index 92f4fc0f6..99a3576a7 100644 --- a/content/features/te-cli/te-cli-migrate.md +++ b/content/features/te-cli/te-cli-migrate.md @@ -2,7 +2,7 @@ uid: te-cli-migrate title: Migrating from the TE2 Command Line author: Peer Grønnerup -updated: 2026-09-11 +updated: 2026-10-27 applies_to: products: - product: Tabular Editor 2 @@ -38,6 +38,13 @@ te Model.bim -S fix.csx -D "localhost\tabular" MyDB -O > [!NOTE] > TE2 mode runs the same `Load → Scripts → Schema Check → Save → BPA → Deploy → TRX` pipeline as `TabularEditor.exe`, including context-sensitive flag behavior (e.g., `-S` after `-D` means `-SHARED`, not `-SCRIPT`). +Scripts (`-S`) in TE2 mode behave as they did in Tabular Editor 2: + +- **A failed script stops the run.** If a script throws or doesn't compile, the run exits with code `1` before anything is saved, analyzed or deployed. There is no build output (`-B`, `-F`, `-TMDL`), no BPA result and no `-T` file, and any output from an earlier run is left as it was. A pipeline step that always reads the `.trx` file must handle it being absent. +- **Compile errors show where they are.** Each error is written to stdout as `Error on line , col : `. With `-V` or `-G`, it becomes an annotation that points at the line in the script file. +- **Each script runs as one change.** Follow-on changes, such as fixing up DAX that refers to a renamed column, are applied when the script ends rather than after each statement. A script that renames a column and then reads a measure that uses it sees the old expression until the script ends. +- **`TECLI` is defined.** Scripts see the `TECLI` preprocessor symbol and not `TE3`, as with `te script`. Tabular Editor 2 defines neither. + ## The migrate command Use `te util migrate` as a live reference for how TE2 flags map to the new CLI. It prints a colorized table of every known TE2 flag, its status (supported, renamed, planned), and the equivalent `te` command. @@ -75,12 +82,12 @@ Below is a non-exhaustive summary of the most commonly used flags. Run `te util | `-M` / `-MEMBERS` | `te deploy --deploy-role-members` | | | `-FULL` (after `-D`) | `te deploy --deploy-full` | Equivalent to overwrite + connections + partitions + shared + roles + role-members. | | `-X` / `-XMLA ` | `te deploy ... > ` (omit `--execute`) | Script emission is the default: without `--execute`, deploy connects read-only and prints the TMSL to stdout - redirect it to a file. | -| `-V` / `-VSTS` | `--ci vsts` on `validate`, `bpa run`, `deploy`, `test run` | Emits `##vso[...]` annotations to stderr. `azdo` and `azure-devops` are accepted aliases. | +| `-V` / `-VSTS` | `--ci vsts` on `validate`, `bpa run`, `schemacheck`, `deploy`, `test run` | Emits `##vso[...]` annotations to stderr. `azdo` and `azure-devops` are accepted aliases. | | `-G` / `-GITHUB` | `--ci github` (alias `gh`) | Emits `::error::` / `::warning::` / `::notice::` annotations. | -| `-T` / `-TRX ` | `--trx ` on `validate`, `bpa run`, `test run` | VSTEST `.trx` file for Azure DevOps test publishing. | +| `-T` / `-TRX ` | `--trx ` on `validate`, `bpa run`, `schemacheck`, `test run` | VSTEST `.trx` file for Azure DevOps test publishing. | | `-W` / `-WARN` | (default) | Warnings always reported in deploy results. | | `-E` / `-ERR` | (default) | Deploy returns non-zero exit on DAX errors. | -| `-SC` / `-SCHEMACHECK` | *Not yet implemented.* | TE2 schema check connects to actual data sources. Different from `te validate` (DAX semantic validation, no data source connection). | +| `-SC` / `-SCHEMACHECK` | `te schemacheck` | Same exit codes as TE2, and checks more kinds of tables - see [Schema check](#schema-check). | | `-L` / `-LOGIN ` (after `-D`) | `te auth login -u -p -t ` | Use service principal or env-based credentials. The login is cached, so subsequent commands acquire tokens silently - see @te-cli-auth. | ## Migration playbook @@ -90,9 +97,10 @@ The recommended path from a TE2-based pipeline to the new CLI: 1. **Drop-in replacement.** Replace `TabularEditor.exe` with `te` (or `te2`) in your existing pipeline. Verify the pipeline still runs - TE2 compatibility handles most invocations unchanged. 2. **Replace flags incrementally.** Convert one flag group at a time: - Start with `-A` / `-AX` → `te bpa run` to pick up richer BPA output (`--fail-on`, `--fix`, `--trx`). + - Then `-SC` → `te schemacheck`, which also checks Power Query and Direct Lake tables. - Then `-D` → `te deploy` for fine-grained deploy control. - Finally `-V` / `-G` → `--ci vsts` / `--ci github`. -3. **Switch to non-interactive CI flags.** Add `--non-interactive` to every `te` command (and `--ci ` on `validate`, `bpa run`, `deploy`, and `test run`), pass `--execute --force` on `deploy`/`refresh` steps that must act, and remove any `start /wait` wrappers - the new CLI is a regular console binary and doesn't need them. +3. **Switch to non-interactive CI flags.** Add `--non-interactive` to every `te` command (and `--ci ` on `validate`, `bpa run`, `schemacheck`, `deploy`, and `test run`), pass `--execute --force` on `deploy`/`refresh` steps that must act, and remove any `start /wait` wrappers - the new CLI is a regular console binary and doesn't need them. 4. **Adopt service principal auth.** Replace `-D -L ` with `te auth login -u ... -p ... -t ...` or an environment-credential pipeline step. See @te-cli-auth. ## Important differences @@ -103,6 +111,21 @@ The recommended path from a TE2-based pipeline to the new CLI: - **No `start /wait` needed.** The new CLI is a regular console binary; invoke it directly in shell scripts, PowerShell, and CI tasks. - **Cross-platform.** The CLI runs on Windows, macOS, and Linux. Local SSAS and Power BI Desktop connections remain Windows-only. +## Schema check + +There are two ways to run Tabular Editor 2's schema check with the new CLI: + +- **`te2 -SC`** works as before. It checks only the tables Tabular Editor 2 checked, legacy query partitions on a provider data source, and writes the same `-T` results. Use it to move a pipeline over without changing its result. +- **[`te schemacheck`](xref:te-cli-commands#schemacheck)** is the command for new pipelines. It also checks Power Query (M) and Direct Lake tables, and supports JSON output. + +Both use Tabular Editor 2's exit codes: an added or retyped source column is a warning and exits with code `0`, and a missing source column, or a legacy query that can't be read, is an error and exits with code `1`. Both honor Tabular Editor 2's schema check annotations, except `TabularEditor_AddFalseWhereClause`. + +Differences from Tabular Editor 2: + +- **Some sources are no longer checked.** A legacy query partition on Oracle, ODBC, or an OLE DB provider other than SQL Server is listed under **Not checked** and doesn't fail the run. The SQL Server OLE DB providers are checked on Windows only. +- **The `-T` file from `te2 -SC` matches Tabular Editor 2's.** It has four results per table, named `Table '' `, so Azure DevOps keeps the test history. A table on one of the sources above gets four **Inconclusive** results. `te schemacheck --trx` writes a different file, with one result per finding. +- **Duplicate source columns no longer stop the run.** Tabular Editor 2 showed a dialog box when a source returned the same column twice. The CLI reports it once as information. + ## Related pages - @command-line-options - the legacy TE2 command-line reference. diff --git a/content/features/te-cli/te-cli.md b/content/features/te-cli/te-cli.md index 8c5719ca1..49d3bee8e 100644 --- a/content/features/te-cli/te-cli.md +++ b/content/features/te-cli/te-cli.md @@ -2,7 +2,7 @@ uid: te-cli title: Tabular Editor CLI (Limited Public Preview) author: Peer Grønnerup -updated: 2026-09-11 +updated: 2026-10-27 applies_to: products: - product: Tabular Editor 2 @@ -51,7 +51,7 @@ See @te-cli-commands for a full command reference with syntax, options, and exam | [Model initialization and save](xref:te-cli-commands#model-initialization-and-save) | Save, convert, initialize models | [`te save-as`](xref:te-cli-commands#save-as), [`te init`](xref:te-cli-commands#init) | | [Model Editing](xref:te-cli-commands#model-editing) | Get/set properties, add/remove/move objects | [`te set`](xref:te-cli-commands#set), [`te add`](xref:te-cli-commands#add), [`te remove`](xref:te-cli-commands#remove), [`te move`](xref:te-cli-commands#move) | | [Inspection](xref:te-cli-commands#inspection) | List objects, search, diff, dependency analysis | [`te list`](xref:te-cli-commands#list), [`te find`](xref:te-cli-commands#find), [`te diff`](xref:te-cli-commands#diff), [`te deps`](xref:te-cli-commands#deps) | -| [Analysis & Quality](xref:te-cli-commands#analysis-and-quality) | Validate, run BPA, format DAX and M, analyze storage | [`te validate`](xref:te-cli-commands#validate), [`te bpa run`](xref:te-cli-commands#bpa-run), [`te util`](xref:te-cli-commands#utilities), [`te vertipaq`](xref:te-cli-commands#vertipaq) | +| [Analysis & Quality](xref:te-cli-commands#analysis-and-quality) | Validate, run BPA, check source schema drift, format DAX and M, analyze storage | [`te validate`](xref:te-cli-commands#validate), [`te bpa run`](xref:te-cli-commands#bpa-run), [`te schemacheck`](xref:te-cli-commands#schemacheck), [`te util`](xref:te-cli-commands#utilities), [`te vertipaq`](xref:te-cli-commands#vertipaq) | | [Execution](xref:te-cli-commands#execution) | Run DAX queries, C# scripts, macros | [`te query`](xref:te-cli-commands#query), [`te script`](xref:te-cli-commands#script), [`te macro`](xref:te-cli-commands#macro) | | [Deployment & Refresh](xref:te-cli-commands#deployment-and-refresh) | Deploy to workspace, trigger refresh, apply refresh policies | [`te deploy`](xref:te-cli-commands#deploy), [`te refresh`](xref:te-cli-commands#refresh) | | [Testing](xref:te-cli-commands#testing) | Assertion tests, snapshots, A/B comparison | [`te test run`](xref:te-cli-commands#test-run) | @@ -91,7 +91,7 @@ te config set hidePreviewNotice true ``` > [!WARNING] -> The banner reappears on every command within **14 days of the preview end date** (2026-10-31), regardless of `hidePreviewNotice`. This ensures you have visible warning before the CLI stops functioning. +> The banner reappears on every command within **14 days of the preview end date** (2026-12-31), regardless of `hidePreviewNotice`. This ensures you have visible warning before the CLI stops functioning. ## License outlook