持续集成 (CI) 样式验证器使用 LookML 样式检查器在整个 LookML 项目中强制执行 LookML 编码标准、命名惯例和结构最佳实践。通过根据一组可配置的样式规则检查 LookML 文件,样式验证器可帮助您的团队维护干净、一致且可读的代码库。
如需运行样式验证器,您必须在 LookML 项目仓库的根目录中添加名为 lkmlstyle.yaml(或 lkmlstyle.yml)的配置文件。如需详细了解如何配置样式检查器,请参阅本页面的配置文件部分。
如需了解如何在 CI 套件中配置和运行样式验证器以及查看验证输出,请参阅创建持续集成套件、运行持续集成套件和查看 CI 运行的结果文档页面。
准备工作
如需在持续集成中使用样式验证器,您需要以下各项:
- 运行 Looker 26.18 或更高版本且满足 CI 要求并已启用 CI 的 Looker 实例。
- 已配置 Git 版本控制的 LookML 项目。
- 在 CI 套件设置中启用了样式验证器切换开关(样式验证器默认处于停用状态)。当您开启样式验证器时,系统会默认启用仅增量错误选项。
- LookML 项目仓库根目录中的
lkmlstyle.yaml(或lkmlstyle.yml)配置文件。请参阅本页面上的配置文件部分。
配置文件
如需在 Looker CI 中运行样式验证器,必须提供配置文件。样式验证器运行时,会自动按以下优先级顺序检查 LookML 项目代码库的根目录中是否存在配置文件:
lkmlstyle.yamllkmlstyle.yml
如果这两个文件都存在于根目录中,则 lkmlstyle.yaml 优先,lkmlstyle.yml 会被忽略。
如果在项目根目录中找不到 lkmlstyle.yaml 和 lkmlstyle.yml,并且没有通过 API 传递任何自定义配置,则样式验证运行会失败,并显示错误 "No style validator configuration provided"。
如需使用默认设置运行所有 25 条标准内置规则,您可以在 lkmlstyle.yaml 文件中使用以下最少的配置信息:
schema_version: 1
ruleset_version: "all-v1.0"
否则,您可以自定义配置文件。配置文件可以包含以下顶级参数:
| 参数 | 类型 | 是否必需? | 默认 | 说明 |
|---|---|---|---|---|
schema_version |
整数 | 是 | 无 | 配置架构版本。版本 1 是唯一受支持的版本,必须明确指定。 |
ruleset_version |
字符串 | 是 | 无 | 要继承的基准规则集版本。支持的值:"all-v1.0"、"none"。 |
ignore_files |
字符串列表 | 否 | [] |
要完全从样式验证中排除的文件的 glob 模式。 |
rules |
地图 | 否 | {} |
针对各个规则的全局自定义设置(severity 和 version)。还可以启用基准规则集不包含的内置规则,并更改自定义规则的严重程度。如需查看示例,请参阅规则自定义部分。 |
overrides |
地图列表 | 否 | [] |
用于调整或启用特定匹配文件路径的严重程度的范围规则替换项。 |
custom_rules |
地图列表 | 否 | [] |
声明式的用户自定义规则。 |
ruleset_version
ruleset_version 参数定义了样式验证策略的基础:
"all-v1.0"(推荐):激活 25 条标准内置 LookML 样式规则,严重程度为error。此选项非常适合希望开箱即用且全面强制执行质量标准的团队。"none":从启用零个内置规则开始。此选项非常适合希望逐步采用样式验证、逐个选择启用特定规则或仅运行自定义组织规则的团队。当ruleset_version为"none"时,如需选择启用内置规则,请在rules块或overrides块中为该规则分配warn或error严重程度。
ignore_files
ignore_files 参数接受 glob 模式列表,用于指定在样式验证期间要完全绕过的文件。系统不会检查与这些模式匹配的文件是否符合内置规则或自定义规则。
支持的通配符语法包括:
*:匹配单个目录级别中的任何非分隔符字符序列。**:匹配多个嵌套目录级别中的任意字符序列。?:匹配任意单个字符。{a,b}和[abc]:匹配替代项和字符类(Java glob 语法)。
以下路径匹配规则适用于配置文件中的每个 glob 模式,包括顶级 ignore_files 以及 overrides 中的 files 和 ignore_files:
- 路径相对于项目根目录。系统会忽略开头的
./或/。 - 不含斜杠 (
/) 的模式可在任何目录深度进行匹配。例如,*.ignore.lkml同时与x.ignore.lkml和views/x.ignore.lkml匹配。 - 以
/结尾的模式会匹配相应目录下的所有内容。 - 以
.lkml或.lookml结尾的模式也会匹配复合扩展名。例如,*.ignore.lkml与x.ignore.view.lkml匹配。
以下示例排除了供应商文件、旧版 LookML 文件和 LookML 信息中心:
ignore_files:
- "vendor/**"
- "legacy/**/*.lkml"
- "*.ignore.lkml"
- "dashboards/*.dashboard.lookml"
rules
您可以使用 rules 块来调整整个项目中各个规则的诊断严重程度:
rules:
boolean-dimension-name-prefix:
severity: warn
view-dimension-order:
severity: disabled
numeric-measure-value-format-presence:
severity: error
rules(或 overrides 块)中列出的任何严重程度为 warn 或 error 的内置规则都是有效的,即使 ruleset_version 设置为 "none" 也是如此。例如,以下初始配置以 ruleset_version: "none" 开头,并且仅启用两个内置规则:
schema_version: 1
ruleset_version: "none"
rules:
join-relationship-presence:
severity: error
explore-label-presence:
severity: warn
您还可以使用 rules 块通过引用自定义规则的名称来更改其严重程度。
severity
您可以为每条规则配置以下任一严重程度级别(不区分大小写):
error:视为严重违规。错误会导致 CI 运行失败。warn:作为非阻塞警告发出。警告会显示在 CI 运行报告中,但不会导致 CI 运行失败。disabled:完全停用规则,并在验证期间跳过该规则。
overrides
您可以使用 overrides 参数修改特定文件或目录的规则严重程度,而无需更改 LookML 项目其余部分的严重程度。例如,当 ruleset_version 为 "none" 时,您可以使用 overrides 来放宽针对临时视图或旧版模型的规则、收紧针对关键路径的规则,或仅针对特定目录启用特定规则。
overrides 列表中的每个条目都支持以下字段:
| 字段 | 类型 | 是否必需? | 说明 |
|---|---|---|---|
files |
字符串列表 | 是 | 与此替换块所适用的文件匹配的 Glob 模式。群组名称不得为空。 |
ignore_files |
字符串列表 | 否 | 要从此特定替换块中排除的 glob 模式。 |
rules |
地图 | 是 | 规则名称与严重程度配置的映射。不得为空。在替换块中,仅允许(且必须)使用 severity。规则名称必须是有效的内置规则名称或自定义规则名称。 |
以下示例针对旧版视图和信息中心停用了维度排序检查,并将缺少说明的错误降级为警告:
overrides:
- files:
- "views/legacy/**"
- "dashboards/*.dashboard.lookml"
ignore_files:
- "views/legacy/core_*.view.lkml"
rules:
view-dimension-order:
severity: disabled
visible-dimension-description-presence:
severity: warn
custom_rules
您可以在配置文件的 custom_rules 部分中定义声明性自定义规则,以强制执行组织特定的命名惯例、必需的架构模式和结构治理。
每个自定义规则定义都支持以下通用参数:
| 字段 | 类型 | 是否必需? | 说明 |
|---|---|---|---|
name |
字符串 | 是 | 唯一标识符,按照惯例采用连字号格式,例如 finance-measure-prefix。不得与内置规则名称或其他自定义规则冲突。 |
title |
字符串 | 是 | 发生违规行为时报告的人类可读消息,格式为 (<rule-name>) <title>。 |
rule_type |
字符串 | 是 | 规则的原型:pattern_match、property、order、first_child 或 unique。不区分大小写;pattern 可作为 pattern_match 的别名。 |
severity |
字符串 | 否 | 诊断级别:error(默认)、warn 或 disabled。可被 rules 和 overrides 替换。 |
rationale |
字符串 | 否 | 记录规则存在的原因。 |
select |
字符串或列表 | 否 | 目标抽象语法树 (AST) 节点路径,例如 "view.dimension"、"explore" 或 ["dimension", "dimension_group"]。如果省略,规则将以与 filters 匹配的每个节点为目标。 |
filters |
地图 | 否 | 必须与目标节点匹配的属性过滤条件,例如 primary_key: true。 |
parent_filters |
地图 | 否 | 必须与目标节点的直接父级匹配的属性过滤条件。 |
每种规则类型仅接受其自身类型特定的密钥。未知键或属于其他规则类型(例如 pattern_match 规则上的 order_by)的键会导致配置错误。
select
select 参数用于确定自定义规则评估哪些 LookML 元素:
- 直接元素:定位到特定的 LookML 元素类型,例如
select: "dimension"、select: "measure"、select: "view"、select: "explore"、select: "join"、select: "model"或select: "include"。 - 嵌套的父子路径:在特定直接父级(例如
select: "view.dimension"[在视图内定义的维度] 或select: "explore.join"[在探索内定义的联接])内定义的目标元素。父级必须是直接父级,并且仅使用路径的最后两个段(因此a.b.c的行为类似于b.c)。 - 多个目标:使用以逗号分隔的字符串或列表(例如
select: "dimension, dimension_group"或select: ["dimension", "dimension_group"])定位多个元素类型。
选择器、过滤条件和子名称是区分大小写的精确 LookML 关键字。拼写错误的名称不会报告为配置错误,而是永远不会匹配相应规则。
filters和parent_filters之间
您可以使用 filters 和 parent_filters 根据 LookML 文件中明确声明的 LookML 属性来优化目标节点。
- 布尔值相等性:匹配明确声明的布尔值属性,例如
primary_key: true或hidden: true。 - 字符串相等:匹配确切的字符串值,例如
type: "yesno"或type: "count"。 - “任一”列表:匹配列表中的任意值,例如
type: ["string", "number", "date"]。 - 存在性检查:通过传递空字符串(例如
derived_table: "")来检查某个块或属性是否存在。 - 否定:在键或值前面添加
!可否定过滤条件。否定键必须用英文引号括起来,因为未加英文引号的前导!是 YAML 标记语法,会导致配置文件解析失败:"!hidden": true或hidden: "!true"匹配可见(非隐藏)项,包括未声明hidden的字段。type: ["!yesno", "!date"]匹配既不是yesno也不是date的类型。
rule_type
每条自定义规则都必须为 rule_type 参数指定以下五种规则原型之一:
pattern_match
对 LookML 实体名称或属性值强制执行正则表达式模式。您必须指定 match 或 should_not_match 中的一个(如果同时设置了这两个属性,则仅应用 match,并默默忽略 should_not_match):
match(字符串,正则表达式):目标必须匹配的模式。should_not_match(字符串,正则表达式):目标不得匹配的模式。
模式是 Java 正则表达式,在加载配置文件时会进行验证。匹配是非锚定的(子字符串匹配);例如,match: "fin_" 通过了 my_fin_total 的测试。使用 ^ 和 $ 匹配整个值。
如果 select 针对的是属性而非实体(例如 select: "measure.sql" 或 select: "dimension.label"),则系统会针对属性的值而非实体名称评估正则表达式。内置的 measure-sql-table-reference 和 dimension-label-redundant-yes-no 规则就是以这种方式运行的。
以下示例强制规定币种衡量指标必须以 _usd 或 _eur 结尾:
- name: currency-measure-suffix
title: "Currency measures must end with a currency code like _usd or _eur"
rule_type: pattern_match
severity: error
select: "view.measure"
filters:
value_format_name: ["usd", "usd_0", "eur", "eur_0"]
match: "^.*_(usd|eur)$"
禁止使用临时维度或草稿维度的示例:
- name: forbid-temporary-dimensions
title: "Dimensions must not start with 'tmp_' or 'test_'"
rule_type: pattern_match
severity: error
select: "dimension"
should_not_match: "^(tmp|test)_.*"
property
强制要求 LookML 对象中必须存在或禁止存在特定子属性。您必须指定 requires_child 或 forbidden_child 中的一个(如果同时设置了这两个属性,则仅应用 requires_child,并默默忽略 forbidden_child):
requires_child(字符串或列表):必须存在的子属性名称。指定列表时,如果存在所列出的任何一个子级,则满足相应规则。forbidden_child(字符串或列表):不得存在的子属性名称。指定列表后,如果存在列表中的任何子节点,系统都会标记相应节点。child_filters(地图,可选):必需子级必须满足的其他属性过滤条件。
需要为所有可见维度添加说明的示例:
- name: require-visible-dimension-description
title: "Visible dimensions must specify a description"
rule_type: property
severity: warn
select: "view.dimension"
filters:
"!hidden": true
requires_child: "description"
禁止在派生表上使用 sql_table_name 的示例:
- name: forbid-sql-table-name-on-derived-views
title: "Derived table views cannot specify sql_table_name"
rule_type: property
severity: error
select: "view"
filters:
derived_table: ""
forbidden_child: "sql_table_name"
order
强制容器内的同级元素按字母顺序排列。
order_by(字符串,必需):要排序的同级子项的 LookML 类型,通常为"dimension"或"measure"。系统只会比较所选节点的直接子级,而不会将dimension_group子级包含在"dimension"下。
系统会根据字符代码以区分大小写的方式比较名称:大写字母的排序在前,小写字母的排序在后,而 _ 的排序介于两者之间。
示例:要求在视图中按字母顺序列出维度:
- name: custom-alphabetical-dimensions
title: "Dimensions must be kept in alphabetical order within views"
rule_type: order
severity: error
select: "view"
order_by: "dimension"
first_child
强制要求匹配特定过滤条件的元素显示为其类别的第一个子元素。
position(字符串,可选):位置限制。必须为"first"(默认为"first")。
对于 first_child 规则,select 必须采用 parent.child_type 形式,例如 "view.dimension"。filters 参数用于标识必须首先显示的子节点,不会缩小要检查的父节点的范围。架构接受 parent_filters 参数,但对于此规则类型,系统会忽略该参数。
需要先在视图中声明主键维度的示例:
- name: custom-primary-key-first-dimension
title: "Primary key dimension must be the first dimension in the view"
rule_type: first_child
severity: error
select: "view.dimension"
filters:
primary_key: true
position: first
unique
强制在 CI 运行期间验证的文件中所有匹配的节点之间实现属性值的唯一性。
unique_property(字符串,必需):必须在匹配的节点中具有唯一值的属性的名称,例如"sql_table_name"或"label"。
系统会以精确字符串的形式比较值,并报告第一个出现的值和每个重复的值。如果验证运行仅检查项目的部分文件,则不会检测到该子集之外的文件中的重复项。
确保所有视图中的表名称都是唯一的示例:
- name: custom-sql-table-name-uniqueness
title: "Each view must reference a unique sql_table_name"
rule_type: unique
severity: error
select: "view"
unique_property: "sql_table_name"
自定义规则限制条件
创建自定义规则时,请遵守以下限制:
- 不与内置规则名称冲突:自定义规则不能重复使用内置规则目录中的任何名称,例如
boolean-dimension-name-prefix或sql-table-name-uniqueness。 - 唯一的自定义名称:每个自定义规则在
custom_rules列表中都必须具有唯一的名称。 - 连字线格式:规则名称应使用连字线格式 (
lowercase-words-with-hyphens)。
配置评估顺序
当样式验证器评估 LookML 文件时,配置规则会按以下顺序应用:
- 文件排除:如果文件与
ignore_files中的任何格式匹配,则完全跳过该文件。 - 有效规则:文件的有效规则包括
ruleset_version(all-v1.0或none)中的规则,以及在rules或匹配的overrides块中分配了warn或error严重程度的任何内置规则,以及custom_rules中定义的所有规则。 - 严重程度解析:对于每个有效规则,以下设置中第一个指定严重程度的设置具有优先权:最后一个匹配的
overrides块,然后是全局rules块,然后是自定义规则自己的severity,最后是默认严重程度 (error)。 - 已停用的规则:对于相应文件,系统会跳过已解决的严重程度为
disabled的规则。
示例配置文件
以下示例展示了一个完整的 lkmlstyle.yaml 文件,其中演示了基准规则集选择、文件排除、全局规则自定义、范围限定的替换和自定义规则:
# Schema version
schema_version: 1
# Baseline ruleset edition (all-v1.0 or none)
ruleset_version: "all-v1.0"
# Files completely ignored by the style validator
ignore_files:
- "vendor/**"
- "*.ignore.lkml"
- "legacy_dashboards/*.dashboard.lookml"
# Built-in rule customizations
rules:
view-dimension-order:
severity: warn
numeric-measure-value-format-presence:
severity: warn
sql-table-name-uniqueness:
severity: error
# Replaced by the custom first_child rule below
primary-key-first-dimension:
severity: disabled
# Directory/file scoped overrides
overrides:
- files:
- "views/staging/**"
rules:
visible-dimension-description-presence:
severity: disabled
primary-key-visibility:
severity: warn
# Custom rules catalog
custom_rules:
# 1. Pattern Match: Finance dimensions must start with fin_
- name: finance-dimension-prefix
title: "Finance dimensions must be prefixed with fin_"
rule_type: pattern_match
severity: error
rationale: "Ensures clarity in the field picker for finance metrics."
select: "view.dimension"
filters:
view_label: "Finance"
match: "^fin_[a-z0-9_]+$"
# 2. Pattern Match: Forbid draft or test views
- name: forbid-draft-views
title: "Views cannot be named with draft_ or test_ prefixes"
rule_type: pattern_match
severity: error
select: "view"
should_not_match: "^(draft|test)_.*"
# 3. Property: Require explicit relationship on joins
- name: require-join-relationship
title: "All joins must declare an explicit relationship"
rule_type: property
severity: error
select: "explore.join"
requires_child: "relationship"
# 4. Property: Explores must not use sql_always_where
- name: forbid-sql-always-where
title: "Explores should use always_filter instead of sql_always_where"
rule_type: property
severity: warn
select: "explore"
forbidden_child: "sql_always_where"
# 5. Order: Dimension groups inside views must be alphabetical
- name: view-dimension-groups-alphabetical
title: "Dimension groups must appear in alphabetical order within views"
rule_type: order
severity: warn
select: "view"
order_by: "dimension_group"
# 6. First Child: Primary key must be the first dimension
- name: custom-primary-key-first-dimension
title: "The primary key must be defined as the first dimension in the view"
rule_type: first_child
severity: error
select: "view.dimension"
filters:
primary_key: true
position: first
# 7. Unique: Views must not share the same label
- name: unique-view-labels
title: "Views must have unique labels"
rule_type: unique
severity: warn
select: "view"
unique_property: "label"
验证范围和结果
以下部分介绍了样式验证器检查哪些文件以及如何报告验证结果:
已验证的文件
- 系统只会验证根项目中的
.lkml和.lookml文件。系统不会验证导入的(本地或远程)依赖项目。 - 系统会根据每个文件自身的内容对其进行验证。系统不会遵循
include:语句,也不会验证通过include:语句拉取的对象是否属于包含文件。 - 由 dbt Cloud CI 作业触发的 CI 运行会验证生产 LookML 分支,而不是开发分支。
通过或失败行为和输出
- 只有当至少一个诊断信息的严重程度为
error时,样式验证器运行才会失败。仅出现警告不会导致运行失败。 - 在 CI 运行结果页面上,每项诊断结果都包含规则名称、路径、行号、上下文代码段以及指向规则文档的链接。如需详细了解如何运行套件和查看结果,请参阅运行持续集成套件和查看 CI 运行的结果。
- 如果配置文件无效,系统会在第 1 行的配置文件上生成一个
invalid-config错误,并且验证运行失败。
增量验证
您可以在创建或修改持续集成套件时,在样式验证器部分中选中仅增量错误复选框(默认处于选中状态),以针对样式验证器启用增量验证。
启用增量验证后,样式验证器只会报告开发分支上新增的违规情况:
- 它会验证开发分支。
- 它会使用开发分支的配置文件验证目标分支。
- 它只会报告目标分支中尚不存在的违规问题。
请注意,启用增量验证后,系统会执行以下操作:
- 目标分支上预先存在的违规行为不会导致运行失败。
- 由于开发分支的配置文件用于验证这两个分支,因此开发分支上的配置更改无法隐藏预先存在的违规行为,也无法使预先存在的 LookML 本身显示为新的违规行为。
- 开发分支必须包含
lkmlstyle.yaml(或lkmlstyle.yml)配置文件;否则,运行会因缺少配置而失败。
如果停用仅限增量错误,系统会报告已验证分支上发现的每项违规行为。
内置规则目录
下表列出了 all-v1.0 规则集中提供的所有 25 条标准内置规则:
问题排查
以下部分介绍了在排查样式验证器问题时可能会遇到的常见配置问题和支持的语法变体:
配置错误
加载配置文件时,系统会拒绝以下问题,并将其报告为 invalid-config 错误:
- 未知顶层键或规则配置中的未知键。
- 缺少
schema_version或ruleset_version,或者这两个参数的值不受支持。 - 简写标量严重程度,例如
rule-name: warn。 - 缺少或为空的替换块
files或rules,或者替换块内没有severity的规则配置。 - 替换块中的规则名称未知。
- 名称与另一条自定义规则或内置规则重复的自定义规则。
- 在错误的
rule_type上使用的特定类型密钥(例如,在pattern_match规则上使用order_by)。 - 无效的正则表达式。
- 缺少
order_by参数(对于order规则)或unique_property参数(对于unique规则)。 position值不是first(对于first_child规则)。- 过滤条件键中存在未加引号的前导
!,例如!hidden: true,这属于无效的 YAML 标记语法,会导致配置文件解析失败。
隐性配置问题
- 系统会默默忽略全局
rules块中拼写错误的规则名称。 - 如果
select、filters、parent_filters、requires_child、forbidden_child或order_by中的 LookML 类型名称拼写错误,系统不会引发错误。相反,规则永远不会匹配(或对于requires_child,始终会失败)。 - 同时指定
match和should_not_match,或同时指定requires_child和forbidden_child:系统只会应用每对参数中的第一个参数,而忽略第二个参数。 - 在
first_child规则中指定parent_filters不会产生任何影响,系统会忽略该指定。 - 过滤条件仅匹配在 LookML 文件中明确声明的属性,而不匹配 LookML 默认值(请参阅过滤条件语法)。
pattern_match规则中的正则表达式模式是未锚定的子字符串匹配,除非您使用^和$对其进行锚定(请参阅pattern_match)。
可接受的语法变体
severity和rule_type的值不区分大小写。rule_type: pattern可作为pattern_match的别名。- 系统会忽略
ruleset_version中的前导和尾随空格。