Skip to content

Add a reference lint for transforms, tables and transform tests - #40

Draft
galdre wants to merge 220 commits into
mainfrom
galdre/reference-lint
Draft

galdre wants to merge 220 commits into
mainfrom
galdre/reference-lint

Conversation

@galdre

@galdre galdre commented Oct 27, 2026

Copy link
Copy Markdown
Contributor

Adds representations lint (and a lint({ folder }) export): a check of the references between transforms, tables and transform tests in a folder of representation files. It needs no Metabase.

What it checks

Errors, in the order findings are grouped:

  • schema: a transform, test or table file does not match its schema.
  • duplicate-entity-id, duplicate-target: two files share an entity id; two transforms write one table.
  • dangling-transform-id, wrong-type-transform-id: a test's transform_id names nothing, or names something that is not a transform.
  • transform-cycle: transforms read each other's targets.
  • missing-input, unused-input: a test's inputs do not match the tables its transform reads, by Metabase's rule (transform_testing/validator.clj, table-match?).
  • untestable-transform, duplicate-input, expectation-reads-other-table: the other test refusals Metabase makes from the test alone.

Warnings: unknown-table, input-match-undecided (the match depends on a default schema; pass --default-schema DATABASE=SCHEMA), reads-not-checked (a source is missing or its SQL could not be read).

The tables a transform reads come from a walk of the document alongside its schema, which collects every table_id, the table of every field_id in a query, and the cards, metrics, measures, segments and snippets a query uses, followed to their files. Native SQL is scanned for the tables after FROM and JOIN, with snippets pasted in.

Other changes

  • src/lint-mutations.ts: named, known-broken copies of examples/v1, one or more per rule. The package ships the examples and exports MUTATIONS and mutateExamples.
  • src/lint.snapshot.test.ts: the lint's full output on one broken tree per rule.
  • scripts/lint-parity.ts, run by the Import workflow: compares the lint's reads for each example transform with the tables Metabase lists for a test of it.
  • .github/workflows/release-alpha.yml: the publish-alpha label publishes the PR head as an alpha, as in metabase-cli.
  • examples/v1: one more transform and three transform tests.
  • The lint() function was split into named steps by behavior-preserving refactoring commits (Category 1: …), each checked against a recorded output.

Draft: the full review comes later. The alpha is for the CI runner in metabase-cli (RCI-28).

@galdre galdre added the publish-alpha Publish the PR head to npm as an alpha label Oct 27, 2026
@github-actions github-actions Bot removed the publish-alpha Publish the PR head to npm as an alpha label Oct 27, 2026
@github-actions

Copy link
Copy Markdown

Published @metabase/representations@1.6.1-alpha.galdre-reference-lint.35c31db with dist-tag alpha-galdre-reference-lint.

Install: npm install @metabase/representations@alpha-galdre-reference-lint

@galdre
galdre force-pushed the galdre/reference-lint branch from 35c31db to 62a5d6b Compare October 27, 2026 19:45
@galdre galdre added the publish-alpha Publish the PR head to npm as an alpha label Oct 28, 2026
@github-actions github-actions Bot removed the publish-alpha Publish the PR head to npm as an alpha label Oct 28, 2026
@github-actions

Copy link
Copy Markdown

Published @metabase/representations@1.6.1-alpha.br-galdre-reference-lint.sha-f1106aa with dist-tag alpha-galdre-reference-lint.

Install: npm install @metabase/representations@alpha-galdre-reference-lint

escherize added a commit that referenced this pull request Nov 2, 2026
The self-review of #40 ran no live Metabase. Six of its findings are now
corpus cases, recorded from Metabase, which confirms all six: false
errors on a Python source table_id: null, a field-filter tag's table and
files holding [] or '', and missed refusals of an input for a
field-filter tag's table, a quoted name in another case, and a
source.type of native.

- compare: after an import Metabase took, a lint schema error is a
  difference, since an error says Metabase refuses the file.
- corpus-gen: quoted names in another case than the table's. A run with
  seed 11 found the MBQL form of the quoted-name refusal (an input
  PUBLIC.ORDERS) and expectation SQL with template tags, which Metabase
  cannot parse.
- The keeper starts from the cases the corpus holds, so a new run keeps
  only what they do not cover.
- Write edited files with YAML 1.1's rules, as Metabase and the lint
  read them: 1.2's writer left 2024-01-01 09:00:00 unquoted, a
  timestamp in 1.1. gen-7-0 failed to import only for that; drop it.
galdre added 24 commits November 2, 2026 15:08
Metabase ships the Sample Database as SQLite, whose tables have no schema. The examples name its tables with a null schema again, as on main, and the settings file gives it engine sqlite and a null default schema. Tests that needed an engine with schemas use the warehouse or their own H2 database.
A field-filter tag whose field names a table with a null schema does not make every run fail: without a value the tag compiles to 1 = 1. null-schema-reference now says the tag's field names a table that Metabase cannot find at pull, and keeps its message for a query that reads the table.
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