LoginSignup
1
0

More than 1 year has passed since last update.

GitHub ActionsでdbtのCI/CDを実装する①自動テスト

Last updated at Posted at 2023-04-23

概要

この記事ではdbtのドキュメントを参考に、GitHub Actionsを用いてdbtプロジェクトのCI/CDを実装していきます。
実装するワークフローは以下の2つです。

  1. コミットのpush時に自動実行されるワークフロー
    処理内容:SQLFluffを用いてLintする
  2. pull requestがマージされた時に自動実行されるワークフロー
    処理内容:dbt Cloud APIを呼び出してdbtのjobを実行する

※ この記事では既にdbtプロジェクトが存在し、dbtのjobも作成済みの状態を前提としています。

1. コミットのpush時に自動実行されるワークフロー

早速1つ目のCIワークフローから実装していきます。

dbtプロジェクトへの処理追加

まずプロジェクトのルートディレクトリに.githubフォルダを作成し、さらにその中にworkflowsフォルダを作成し、そこにlint_on_push.ymlというファイルを作成します。

my_project
├── .github
│   ├── workflows
│   │   └── lint_on_push.yml

lint_on_push.ymlファイルの中身には以下を記述します。

lint_on_push.yml
name: lint dbt project on push

on:
  push:
    branches-ignore:
      - 'main'

jobs:
# this job runs SQLFluff with a specific set of rules
  # note the dialect is set to Snowflake, so make that specific to your setup
  # details on linter rules: https://docs.sqlfluff.com/en/stable/rules.html
  lint_project:
    name: Run SQLFluff linter
    runs-on: ubuntu-latest
  
    steps:
      - uses: "actions/checkout@v3"
      - uses: "actions/setup-python@v2"
        with:
          python-version: "3.9"
      - name: Install SQLFluff
        run: "pip install sqlfluff==0.13.1"
      - name: Lint project
        run: "sqlfluff lint models --dialect snowflake --rules L019,L020,L021,L022"

ワークフロー実行

コードの説明の前にまず実行してみます。
上記の内容でファイルを作成したらコミットしてpushすることで、ワークフローが実行されます。
GitHub上でリポジトリのActionsタブを見てみると、ワークフローが実行され、Lintが成功していることが分かります。
スクリーンショット 2023-04-23 21.23.54.png

コード説明

このワークフローでは、mainブランチ以外にpushされた時にSQLFluffというLinterを用いてLintを行っています。
※ Lint: ざっくり言うとコードのフォーマットなど、書き方に問題がないかチェックする処理

sqlfluff lint modelsによってmodelsディレクトリ配下のSQLに対してLintを行います。
--dialectオプションでベースとなるSQLとしてSnowflakeのSQLを指定していて、--rulesオプションでは以下4つのルールをチェックするように指定しています。

L019: カラムなどを複数指定するときにカンマの位置が行の末尾になっていること
L020: エイリアスでテーブル名を付けたり複数DBからテーブルを参照する時に、テーブル名が一意になっていること
L021: あるカラムに対してGROUP BYとDISTINCTをどちらとも指定してしまっていないこと
L022: CTEの閉じ括弧の後に空行があること

※ これらの4つのルールは例として指定しているだけなので、どのルールを設定するかはチーム毎に決める必要があります。

SQLFluffが他にどんなルールを指定できるかは、ドキュメントのルールに関するページを参照してください。

今回指定した4つのルールのいずれかを違反したSQLの記述があった場合はLintがエラーになります。
試しにCTEを使用している適当なモデルで、以下のようにCTEの閉じ括弧下の空行を削除してコミット&pushしてみます。
スクリーンショット 2023-04-23 21.14.07.png

ワークフローの結果を確認してみると、Lintの実行がエラーになり、L022のルール(CTEの閉じ括弧の後に空行があること)を守れていないことが分かります。
スクリーンショット 2023-04-23 21.10.27.png

Lintが成功するようにコードを戻したら2つ目のワークフロー作成に移ります。

2. pull requestがマージされた時に自動実行されるワークフロー

次は、mainブランチにpushされた時(= pull requestがマージされた時)にdbt Cloud APIを呼び出してdbtのjobを実行するワークフローを実装していきます。

dbt Cloud APIキーの取得

dbt Cloud APIを呼び出すためにAPIキーが必要なので、取得していきます。
まずdbt Cloudの画面で Account Settings ページにアクセスし、ページ下部にある Service Tokens の「New Token」ボタンを押します。
CICD Tokenのような名前を入力し、「+Add」を押してJob Adminの権限を選択し、saveします。

そうするとTokenが作成されるので、コピーして安全な場所で保管しておきます。

GitHubのsecretへの登録

次に、取得したTokenをGitHubリポジトリのsecretに保存していきます。
リポジトリの SettingsSecrets and Variables ドロップダウンにある Actions ページで、「New repository secret」ボタンを押します。
スクリーンショット 2023-04-24 0.56.58.png

Name にはDBT_API_KEYSecrets には作成したTokenを入力し、「Add secret」ボタンを押せば完了です。

dbtプロジェクトへの処理追加

次はdbtプロジェクトの作業に入ります。
プロジェクトのルートディレクトリにpythonフォルダを作成し、run_and_monitor_dbt_job.pyというファイルを作成し、このgistの内容をコピペします。

このpythonファイルでは、渡されたjob IDなどの情報をもとにdbt Cloud APIを呼び出し、jobが成功したら正常終了、失敗したらエラーを投げるというような処理を行います。

では.github/workflows配下にdbt_run_on_merge.ymlを作成します。
この記事で追加したファイルの最終的な構成は以下のようになります。

my_project
├── python
│   └── run_and_monitor_dbt_job.py
├── .github
│   ├── workflows
│   │   └── dbt_run_on_merge.yml
│   │   └── lint_on_push.yml

dbt_run_on_merge.ymlには以下の内容を記述します。

dbt_run_on_merge.yml
name: run dbt Cloud job on push

# This filter says only run this job when there is a push to the main branch
# This works off the assumption that you've restrictred this branch to only all PRs to push to the deafult branch
# Update the name to match the name of your default branch
on:
  push:
    branches:
      - 'main'

jobs:

  # the job calls the dbt Cloud API to run a job
  run_dbt_cloud_job:
    name: Run dbt Cloud Job
    runs-on: ubuntu-latest

  # Set the environment variables needed for the run
    env:
      DBT_ACCOUNT_ID: 00000 # enter your account id
      DBT_PROJECT_ID: 00000 # enter your project id
      DBT_PR_JOB_ID:  00000 # enter your job id
      DBT_API_KEY: ${{ secrets.DBT_API_KEY }}
      DBT_JOB_CAUSE: 'GitHub Pipeline CI Job' 
      DBT_JOB_BRANCH: ${{ github.ref_name }}

    steps:
      - uses: "actions/checkout@v3"
      - uses: "actions/setup-python@v4"
        with:
          python-version: "3.9"
      - name: Run dbt Cloud job
        run: "python python/run_and_monitor_dbt_job.py"

DBT_ACCOUNT_ID, DBT_PROJECT_ID, DBT_PR_JOB_IDには自分の状況にあったIDをそれぞれ入力します。
それぞれのIDはdbt CloudのURLから取得できるので、ブラウザでdbt Cloudのjobのページを開きURLの数字を見ると、左からアカウントIDプロジェクトIDジョブIDに対応しています。

このワークフローでは、mainブランチにpushされた時(= pull requestがマージされた時)に各IDやTokenなどの情報を環境変数としてセットし、先ほど作成したdbt Cloud API呼び出し用のpythonファイルを実行します。

ワークフロー実行

ではコミット&push後、pull requestを作ってマージまで行ってみます。

マージ後にActionsタブを確認すると、作成したワークフローが実行され成功しています。
スクリーンショット 2023-04-24 0.03.29.png

詳細を見てみると、作成したpythonファイルに記述された通りにログが表示され、dbt jobが成功していることも分かります。
スクリーンショット 2023-04-24 0.02.55.png

dbt Cloudの方で実行されたjobを見ると、GitHubのCI Jobから実行されたことや、トリガーになったコミットなども分かります。
スクリーンショット 2023-04-24 2.38.00.png

まとめ

この記事ではdbtのドキュメントを参考に以下のCI/CDを実装しました。

  • push時にLintを行う
  • pull requestのマージ時にdbt Cloud jobを実行する
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0