📊

Looker SDKを使ってLookMLのバリデーションCIを自作した話

に公開

はじめに

こんにちは。ファインディ株式会社でデータエンジニアをやっている田頭啓介(@tagasyksk)です。
この記事は、ファインディ株式会社 Advent Calendar 2025の20日目の記事です。

ファインディではBIツールとしてLookerを利用しています。
最近ではClaude CodeなどのAIを活用してLookMLを開発する機会が増え、CIによる自動検証の重要性がより高まっています。本記事では、GitHub Actionsで行っているLookMLのバリデーションについて紹介します。

LookerのネイティブCIについて

Lookerでは、2025年12月現在プレビュー版として「Looker Continuous Integration」が提供されています。

https://docs.cloud.google.com/looker/docs/continuous-integration?hl=ja

Looker Continuous Integrationでは、次のような検証が可能です。

  • Exploreのディメンションがデータベースに対して正常に実行されるか (SQL Validator)
  • LookMLに記述したデータテストが通るか(Assert Validator)
  • ダッシュボードやLookにエラーが無いか(Contents Validator)
  • LookMLの構文が正しいか(LookML Validator)

これらは全て非常に有用ですが、LookMLに記述したメジャーを検証するCIが存在しません。構文的には正しいLookMLでも、実際にExploreを開いて指標を計算しようとするとエラーになるケースがあり、PRマージ後に初めて問題が発覚することがありました。

そこで、Looker SDKを利用して開発したExplore上のメジャーが正常に計算できるか検証するCIを作成しました。

スクリプト

devワークスペースに切り替えて、ブランチ上のモデルに対してクエリを実行するようにしています。

import os
import sys
import looker_sdk
from looker_sdk import models40, error

OUTPUT_FILE = "validation_result.md"
LIMIT = "1"

MODEL_NAME = os.getenv("LOOKER_MODEL", "your-model-name")
PROJECT_ID = os.getenv("LOOKER_PROJECT")
TARGET_WORKSPACE = os.getenv("LOOKER_WORKSPACE", "dev").lower()
TARGET_BRANCH = os.getenv("LOOKER_GIT_BRANCH")


def main():
    sdk = looker_sdk.init40()
    print(f"認証成功: {sdk.me().display_name}")

    # devワークスペースに切り替え
    setup_workspace(sdk)

    # 検証実行
    success_list, failed_list = run_validation(sdk)

    if len(failed_list) > 0:
        sys.exit(1)


def setup_workspace(sdk):
    """ワークスペースとGitブランチの切り替え"""
    if TARGET_WORKSPACE == "dev":
        sdk.update_session(body=models40.WriteApiSession(workspace_id="dev"))

        if TARGET_BRANCH and PROJECT_ID:
            sdk.update_git_branch(
                project_id=PROJECT_ID,
                body=models40.WriteGitBranch(name=TARGET_BRANCH)
            )
            sdk.reset_project_to_remote(PROJECT_ID)


def run_validation(sdk):
    """Exploreの検証を実行"""
    success_explores = []
    failed_explores = []

    model_info = sdk.lookml_model(lookml_model_name=MODEL_NAME)
    explores = model_info.explores

    for exp_def in explores:
        explore_name = exp_def.name
        print(f"検証中: {explore_name}")

        try:
            explore = sdk.lookml_model_explore(MODEL_NAME, explore_name)

            # 各ViewからDimensionを1つずつ取得
            view_names = set()
            if explore.view_name:
                view_names.add(explore.view_name)
            if explore.joins:
                for j in explore.joins:
                    view_names.add(j.name)

            query_dimensions = []
            if explore.fields and explore.fields.dimensions:
                for v_name in view_names:
                    found_dim = next(
                        (d.name for d in explore.fields.dimensions if d.view == v_name),
                        None
                    )
                    if found_dim:
                        query_dimensions.append(found_dim)

            # Measureを取得
            query_measure = None
            if explore.fields and explore.fields.measures:
              query_measure = explore.fields.measures[0].name

            if not query_dimensions:
                continue
            
            fields = query_dimensions.copy()
            if query_measure:
                fields.append(query_measure)

            # クエリ実行
            query_body = models40.WriteQuery(
                model=MODEL_NAME,
                view=explore_name,
                fields=fields,
                limit=LIMIT
            )
            sdk.run_inline_query(result_format="json", body=query_body)

            success_explores.append(explore_name)

        except error.SDKError as e:
            failed_explores.append({
                "name": explore_name,
                "error": str(e.message) if hasattr(e, 'message') else str(e)
            })

    return success_explores, failed_explores

検証結果はMarkdown形式でファイルに出力し、PRコメントとして投稿するようにしています。

  • 成功時
  • 失敗時

※GitHub Actionsのワークフローは、Pythonスクリプトを呼び出しているだけなので割愛しました。

おわりに

Looker公式のCIでは検出できないExploreの実行エラーを、Looker SDKとGitHub Actionsで検証する仕組みを紹介しました。このCIにより、PRマージ前にExploreの実行エラーを検知できるようになりました。

ファインディでは一緒に会社を盛り上げてくれるメンバーを募集中です。興味を持っていただいた方はこちらのページからご応募お願いします。

https://herp.careers/v1/findy/AC7frF7k9fxm

Discussion