Jenkins を使用した Azure Databricks の CI/CD
注意
この記事では、Databricks によって提供もサポートもされていない Jenkins について説明します。 プロバイダーに問い合わせるには、Jenkins のヘルプを参照してください。
CI/CD パイプラインの管理と実行に使用できる CI/CD ツールは多数あります。 この記事では、Jenkins オートメーション サーバーの使用方法について説明します。 CI/CD は設計パターンなので、この記事に記載されている手順とステージでは、各ツールのパイプライン定義言語にいくつかの変更を加えて転送する必要があります。 さらに、このサンプル パイプラインのコードの多くでは、標準の Python コードが実行されます。これは、他のツールで呼び出すことができます。 Azure Databricks の CI/CD の概要については、「Azure Databricks の CI/CD とは」を参照してください。
Azure Databricks での Azure DevOps の使用方法については、「Azure DevOps を使用した Azure Databricks での継続的インテグレーションとデリバリー」を参照してください。
CI/CD 開発ワークフロー
Databricks は、Jenkins を使用した CI/CD 開発の次のワークフローを提案します。
- サードパーティの Git プロバイダーでリポジトリを作成するか、既存のリポジトリを使用してください。
- ローカル開発マシンを同じサード パーティのリポジトリに接続します。 手順については、サードパーティの Git プロバイダーのドキュメントを参照してください。
- 既存の更新された成果物 (ノートブック、コード ファイル、ビルド スクリプトなど) をサード パーティのリポジトリからローカル開発マシンにプルします。
- 必要に応じて、ローカル開発マシンで成果物を作成、更新、テストしてください。 次に、ローカル開発マシンから、新しい成果物と変更された成果物をサード パーティのリポジトリにプッシュします。 手順については、サードパーティの Git プロバイダーのドキュメントを参照してください。
- 必要に応じて、手順 3 と手順 4 を繰り返します。
- Jenkins を定期的に使用することで、サード パーティのリポジトリから成果物をローカル開発マシンまたは Azure Databricks ワークスペースに自動的にプルし、ローカル開発マシンまたは Azure Databricks ワークスペースでコードをビルド、テスト、実行し、テストおよび実行結果を報告するための統合的なアプローチとして使用できます。 Jenkins は手動で実行できますが、実際の実装では、リポジトリのプル要求など、特定のイベントが発生するたびに Jenkins を実行するようにサードパーティの Git プロバイダーに指示しておくのが一般的です。
この記事の残りの部分では、プロジェクト例を使用して、Jenkins を使用して上記の CI/CD 開発ワークフローを実装する 1 つの方法について説明します。
Jenkins の代わりに、Azure DevOps を使用する方法については、「Azure DevOps を使用した Azure Databricks での継続的インテグレーションとデリバリー」を参照してください。
ローカル開発マシンのセットアップ
この記事の例では、Jenkins を使用して Databricks CLI と Databricks アセット バンドルに次の操作を行うよう指示 します。
- ローカル開発マシンで Python ホイール ファイルをビルドします。
- ビルドされた Python ホイール ファイルと、追加の Python ファイル、Python ノートブックをローカル開発マシンから Azure Databricks ワークスペースにデプロイします。
- アップロードした Python ホイール ファイルとノートブックを、そのワークスペースでテストして実行します。
Azure Databricks ワークスペースに、この例のビルド ステージとアップロード ステージを実行するように指示するためにローカル開発マシンを設定するには、ローカル開発マシンで次の操作を行います。
手順 1: 必要なツールをインストールする
この手順では、ローカル開発マシンに Databricks CLI、Jenkins、jq
、Python ホイール ビルド ツールをインストールします。 この例を実行するには、これらのツールが必要です。
Databricks CLI バージョン 0.205 以降をインストールします (まだインストールしていない場合)。 Jenkins では、Databricks CLI を使用して、この例のテストと実行命令をワークスペースに渡します。 「Databricks CLI のインストールまたは更新」を参照してください。
Jenkins をインストールして起動します (まだインストールしていない場合)。 Linux、macOS、またはWindows 用の Jenkins のインストールを参照してください。
jq をインストールします。 この例では、JSON 形式のコマンド出力を解析するために
jq
を使用します。pip
を使用して、次のコマンドで Python ホイール ビルド ツールをインストールします (一部のシステムでは、pip
の代わりにpip3
を使用する必要があります)。pip install --upgrade wheel
手順 2: Jenkins パイプラインを作成する
この手順では、Jenkins を使用して、この記事の例の Jenkins パイプラインを作成します。 Jenkins には、CI/CD パイプラインを作成するための異なるプロジェクトの種類がいくつか用意されています。 パイプラインでは、Jenkins プラグインを呼び出して構成するために、Groovy コードを使用してパイプライン内のステージを定義するインターフェイスが提供されます。
Jenkins で Jenkins パイプラインを作成するには、次の手順を実行します。
- Jenkins を起動したら、Jenkins ダッシュボードで [新しい項目] をクリックします。
- [項目名の入力] に、Jenkins パイプラインの名前を入力します。例:
jenkins-demo
。 - [パイプライン プロジェクト タイプ] アイコンをクリックします。
- [OK] をクリックします。 Jenkins パイプラインの [構成] ページが表示されます。
- [パイプライン] 領域にて、 [定義] ドロップダウン リストで、SCM から [パイプライン スクリプト] を選択します。
- [SCM] ドロップダウン リストで、[Git] を選択します。
- [リポジトリ URL] には、サードパーティの Git プロバイダーによってホストされているリポジトリの URL を入力します。
- [Branch Specifier]\(ブランチ指定子\) には、
*/<branch-name>
と入力し、<branch-name>
は使用するリポジトリ内のブランチの名前です。例:*/main
。 - [スクリプト パス] には、まだ設定されていない場合は
Jenkinsfile
と入力します。 この記事の後半でJenkinsfile
を作成します。 - [Lightweight checkout]\(ライトウェイト チェックアウト\) というタイトルのチェックボックスが既にオンになっている場合はオフにします。
- [保存] をクリックします。
手順 3: Jenkins にグローバル環境変数を追加する
この手順では、3 つのグローバル環境変数を Jenkins に追加します。 Jenkins は、これらの環境変数を Databricks CLI に渡します。 Databricks CLI では、Azure Databricks ワークスペースで認証するためにこれらの環境変数の値が必要になります。 この例では、サービス プリンシパルに対して OAuth マシン間 (M2M) 認証を使用します (ただし、他の認証タイプも使用できます)。 Azure Databricks ワークスペースに対して OAuth M2M 認証を設定するには、「OAuth(OAuth M2M)を使用してサービスプリンシパルで Azure Databricks へのアクセスを認証する」を参照してください。
この例の 3 つのグローバル環境変数は次のとおりです。
DATABRICKS_HOST
、https://
で始まる Azure Databricks ワークスペースの URL に設定します。 「ワークスペースのインスタンス名、URL、および ID」を参照してください。DATABRICKS_CLIENT_ID
。サービス プリンシパルのクライアント ID (アプリケーション ID とも呼ばれます) に設定されます。DATABRICKS_CLIENT_SECRET
。サービス プリンシパルの Azure Databricks OAuth シークレットに設定されます。
Jenkins でグローバル環境変数を設定するには、Jenkins ダッシュボードから次の手順を実行します。
- サイドバーの [Jenkins の管理] をクリックします。
- [システム構成] セクションで、[システム] をクリックします。
- [グローバル プロパティ] セクションで、タイル化された [環境変数] のチェック ボックスをオンにします。
- [追加] をクリックし、環境変数の [名前] と [値] を 入力します。 追加の環境変数ごとにこれを繰り返します。
- 環境変数の追加が完了したら、[保存] をクリックして Jenkins ダッシュボードに戻ります。
Jenkins パイプラインを設計する
Jenkins には、CI/CD パイプラインを作成するための異なるプロジェクトの種類がいくつか用意されています。 この例では、Jenkins パイプラインを実装します。 パイプラインでは、Jenkins プラグインを呼び出して構成するために、Groovy コードを使用してパイプライン内のステージを定義するインターフェイスが提供されます。
Jenkins パイプライン定義をテキスト ファイル (Jenkinsfile と呼ばれる) で記述します。これは、プロジェクトのソース管理リポジトリにチェックインされます。 詳細については、Jenkins パイプラインに関するページを参照してください。 この記事の例の Jenkins パイプラインを次に示します。 この例の Jenkinsfile
では、次のプレースホルダーを置き換えます。
<user-name>
と<repo-name>
はサードパーティの Git プロバイダーによってホストされているユーザー名とリポジトリ名に置き換えます。 この記事では、GitHub URL を例として使用します。<release-branch-name>
をリポジトリ内のリリース ブランチの名前に置き換えます。 たとえば、main
になります。<databricks-cli-installation-path>
を、Databricks CLI がインストールされているローカル開発マシン上のパスに置き換えます。 たとえば、macOS の場合、これは/usr/local/bin
になります。<jq-installation-path>
を、jq
がインストールされているローカル開発マシン上のパスに置き換えます。 たとえば、macOS の場合、これは/usr/local/bin
になります。- この例では、
<job-prefix-name>
をワークスペースで作成された Azure Databricks ジョブを一意に識別するための文字列に置き換えます。 たとえば、jenkins-demo
になります。 BUNDLETARGET
がdev
に設定されていることに注意してください。これはこの記事の後半で定義されている Databricks アセット バンドル ターゲットの名前です。 実際の実装では、これを独自のバンドル ターゲットの名前に変更します。 バンドル ターゲットの詳細については、この記事の後半で説明します。
リポジトリのルートに追加する必要がある Jenkinsfile
を次に示します。
// Filename: Jenkinsfile
node {
def GITREPOREMOTE = "https://github.com/<user-name>/<repo-name>.git"
def GITBRANCH = "<release-branch-name>"
def DBCLIPATH = "<databricks-cli-installation-path>"
def JQPATH = "<jq-installation-path>"
def JOBPREFIX = "<job-prefix-name>"
def BUNDLETARGET = "dev"
stage('Checkout') {
git branch: GITBRANCH, url: GITREPOREMOTE
}
stage('Validate Bundle') {
sh """#!/bin/bash
${DBCLIPATH}/databricks bundle validate -t ${BUNDLETARGET}
"""
}
stage('Deploy Bundle') {
sh """#!/bin/bash
${DBCLIPATH}/databricks bundle deploy -t ${BUNDLETARGET}
"""
}
stage('Run Unit Tests') {
sh """#!/bin/bash
${DBCLIPATH}/databricks bundle run -t ${BUNDLETARGET} run-unit-tests
"""
}
stage('Run Notebook') {
sh """#!/bin/bash
${DBCLIPATH}/databricks bundle run -t ${BUNDLETARGET} run-dabdemo-notebook
"""
}
stage('Evaluate Notebook Runs') {
sh """#!/bin/bash
${DBCLIPATH}/databricks bundle run -t ${BUNDLETARGET} evaluate-notebook-runs
"""
}
stage('Import Test Results') {
def DATABRICKS_BUNDLE_WORKSPACE_ROOT_PATH
def getPath = "${DBCLIPATH}/databricks bundle validate -t ${BUNDLETARGET} | ${JQPATH}/jq -r .workspace.file_path"
def output = sh(script: getPath, returnStdout: true).trim()
if (output) {
DATABRICKS_BUNDLE_WORKSPACE_ROOT_PATH = "${output}"
} else {
error "Failed to capture output or command execution failed: ${getPath}"
}
sh """#!/bin/bash
${DBCLIPATH}/databricks workspace export-dir \
${DATABRICKS_BUNDLE_WORKSPACE_ROOT_PATH}/Validation/Output/test-results \
${WORKSPACE}/Validation/Output/test-results \
-t ${BUNDLETARGET} \
--overwrite
"""
}
stage('Publish Test Results') {
junit allowEmptyResults: true, testResults: '**/test-results/*.xml', skipPublishingChecks: true
}
}
この記事の残りの部分では、この Jenkins パイプラインの各ステージと、そのステージで Jenkins が実行するための成果物とコマンドを設定する方法について説明します。
サードパーティのリポジトリから最新の成果物をプルする
この Jenkins パイプラインの最初のステージ (Checkout
ステージ) は、次のように定義されています。
stage('Checkout') {
git branch: GITBRANCH, url: GITREPOREMOTE
}
このステージでは、Jenkins がローカル開発マシンで使用する作業ディレクトリに、サードパーティの Git リポジトリからの最新の成果物があることを確認します。 通常、Jenkins はこの作業ディレクトリを <your-user-home-directory>/.jenkins/workspace/<pipeline-name>
に設定します。 これにより、同じローカル開発マシン上で、Jenkins がサード パーティの Git リポジトリから使用する成果物とは別に、開発中の成果物の独自のコピーを保持できます。
Databricks アセット バンドルを検証する
この Jenkins パイプラインの 2 番目のステージ (Validate Bundle
ステージ) は、次のように定義されます。
stage('Validate Bundle') {
sh """#!/bin/bash
${DBCLIPATH}/databricks bundle validate -t ${BUNDLETARGET}
"""
}
このステージでは、成果物をテストおよび実行するためのワークフローを定義する Databricks アセット バンドルが構文的に正しいことを確認します。 Databricks アセット バンドル (単にバンドルとも呼ばれる) では、すべてのデータ、分析および ML プロジェクトを、ソース ファイルのコレクションとして表現できます。 「Databricks アセット バンドルとは」をご覧ください。
この記事のバンドルを定義するには、ローカル コンピューター上の複製されたリポジトリのルートに databricks.yml
という名前を付けたファイルを作成します。 この例の databricks.yml
ファイルでは、次のプレースホルダーを置き換えます。
<bundle-name>
をバンドルの一意なプログラム名に置き換えます。 たとえば、jenkins-demo
になります。- この例では、
<job-prefix-name>
をワークスペースで作成された Azure Databricks ジョブを一意に識別するための文字列に置き換えます。 たとえば、jenkins-demo
になります。 Jenkinsfile 内のJOBPREFIX
値と一致する必要があります。 <spark-version-id>
をジョブ クラスターの Databricks Runtime バージョン ID に置き換えます。例:13.3.x-scala2.12
。<cluster-node-type-id>
をジョブ クラスターのノード タイプ ID に置き換えます。例:Standard_DS3_v2
。targets
マッピングのdev
は、Jenkinsfile 内のBUNDLETARGET
と同じであることに注意してください。 バンドル ターゲットは、ホストと関連するデプロイ動作を指定します。
この例を正しく動作させるには、リポジトリのルートに追加する必要がある databricks.yml
ファイルを次に示します。
# Filename: databricks.yml
bundle:
name: <bundle-name>
variables:
job_prefix:
description: A unifying prefix for this bundle's job and task names.
default: <job-prefix-name>
spark_version:
description: The cluster's Spark version ID.
default: <spark-version-id>
node_type_id:
description: The cluster's node type ID.
default: <cluster-node-type-id>
artifacts:
dabdemo-wheel:
type: whl
path: ./Libraries/python/dabdemo
resources:
jobs:
run-unit-tests:
name: ${var.job_prefix}-run-unit-tests
tasks:
- task_key: ${var.job_prefix}-run-unit-tests-task
new_cluster:
spark_version: ${var.spark_version}
node_type_id: ${var.node_type_id}
num_workers: 1
spark_env_vars:
WORKSPACEBUNDLEPATH: ${workspace.root_path}
notebook_task:
notebook_path: ./run_unit_tests.py
source: WORKSPACE
libraries:
- pypi:
package: pytest
run-dabdemo-notebook:
name: ${var.job_prefix}-run-dabdemo-notebook
tasks:
- task_key: ${var.job_prefix}-run-dabdemo-notebook-task
new_cluster:
spark_version: ${var.spark_version}
node_type_id: ${var.node_type_id}
num_workers: 1
data_security_mode: SINGLE_USER
spark_env_vars:
WORKSPACEBUNDLEPATH: ${workspace.root_path}
notebook_task:
notebook_path: ./dabdemo_notebook.py
source: WORKSPACE
libraries:
- whl: "/Workspace${workspace.root_path}/files/Libraries/python/dabdemo/dist/dabdemo-0.0.1-py3-none-any.whl"
evaluate-notebook-runs:
name: ${var.job_prefix}-evaluate-notebook-runs
tasks:
- task_key: ${var.job_prefix}-evaluate-notebook-runs-task
new_cluster:
spark_version: ${var.spark_version}
node_type_id: ${var.node_type_id}
num_workers: 1
spark_env_vars:
WORKSPACEBUNDLEPATH: ${workspace.root_path}
spark_python_task:
python_file: ./evaluate_notebook_runs.py
source: WORKSPACE
libraries:
- pypi:
package: unittest-xml-reporting
targets:
dev:
mode: development
databricks.yml
ファイルの詳細については、「Databricks アセット バンドルの構成」を参照してください。
ワークスペースにバンドルをデプロイする
Deploy Bundle
というタイトルの Jenkins パイプラインの 3 番目のステージは、次のように定義されています。
stage('Deploy Bundle') {
sh """#!/bin/bash
${DBCLIPATH}/databricks bundle deploy -t ${BUNDLETARGET}
"""
}
このステージでは、次の 2 つの処理が行われます。
databricks.yml
ファイル内のartifact
マッピングがwhl
に設定されているため、指定した場所にあるsetup.py
ファイルを使用して Python ホイール ファイルをビルドするよう Databricks CLI に指示します。- ローカル開発マシン上に Python ホイール ファイルがビルドされると、Databricks CLI は、ビルドされた Python ホイール ファイルを指定された Python ファイルとノートブックと共に Azure Databricks ワークスペースにデプロイします。 既定では、Databricks アセット バンドルは Python ホイール ファイルとその他のファイルを
/Workspace/Users/<your-username>/.bundle/<bundle-name>/<target-name>
にデプロイします。
databricks.yml
ファイルで指定した Python ホイール ファイルをビルドできるようにするには、ローカル コンピューター上の複製したリポジトリのルートに次のフォルダーとファイルを作成します。
ノートブックが実行される Python ホイール ファイルのロジックと単体テストを定義するには、addcol.py
および test_addcol.py
という名前の 2 つのファイルを作成し、リポジトリの Libraries
フォルダー内の python/dabdemo/dabdemo
という名前のフォルダー構造に追加します (簡潔にするために、省略記号はリポジトリ内の省略されたフォルダーを示します)。
├── ...
├── Libraries
│ └── python
│ └── dabdemo
│ └── dabdemo
│ ├── addcol.py
│ └── test_addcol.py
├── ...
addcol.py
ファイルには、Python ホイール ファイルに組み込まれた後、Azure Databricks クラスターにインストールされる可能性があるライブラリ関数が含まれています。 これは、リテラルで入力された新しい列を Apache Spark DataFrame に追加する単純な関数です。
# Filename: addcol.py
import pyspark.sql.functions as F
def with_status(df):
return df.withColumn("status", F.lit("checked"))
test_addcol.py
ファイルには、addcol.py
で定義されている with_status
関数にモック DataFrame オブジェクトを渡すテストが含まれています。 結果は、想定される値を含む DataFrame オブジェクトと比較されます。 値が一致する場合 (この例では一致)、テストは成功します:
# Filename: test_addcol.py
import pytest
from pyspark.sql import SparkSession
from dabdemo.addcol import *
class TestAppendCol(object):
def test_with_status(self):
spark = SparkSession.builder.getOrCreate()
source_data = [
("paula", "white", "paula.white@example.com"),
("john", "baer", "john.baer@example.com")
]
source_df = spark.createDataFrame(
source_data,
["first_name", "last_name", "email"]
)
actual_df = with_status(source_df)
expected_data = [
("paula", "white", "paula.white@example.com", "checked"),
("john", "baer", "john.baer@example.com", "checked")
]
expected_df = spark.createDataFrame(
expected_data,
["first_name", "last_name", "email", "status"]
)
assert(expected_df.collect() == actual_df.collect())
Databricks CLI でこのライブラリ コードを Python ホイール ファイルに正しくパッケージ化するには、__init__.py
と __main__.py
という名前の 2 つのファイルを、前の 2 つのファイルと同じフォルダーに作成します。 また、python/dabdemo
フォルダーに setup.py
という名前のファイルを作成し、次のように視覚化します (簡潔にするために省略記号は省略されたフォルダーを示します):
├── ...
├── Libraries
│ └── python
│ └── dabdemo
│ ├── dabdemo
│ │ ├── __init__.py
│ │ ├── __main__.py
│ │ ├── addcol.py
│ │ └── test_addcol.py
│ └── setup.py
├── ...
__init__.py
ファイルには、ライブラリのバージョン番号と作成者が含まれています。 <my-author-name>
をお客様の名前に置き換えます:
# Filename: __init__.py
__version__ = '0.0.1'
__author__ = '<my-author-name>'
import sys, os
sys.path.append(os.path.join(os.path.dirname(__file__), "..", ".."))
__main__.py
ファイルには、ライブラリのエントリ ポイントが含まれています:
# Filename: __main__.py
import sys, os
sys.path.append(os.path.join(os.path.dirname(__file__), "..", ".."))
from addcol import *
def main():
pass
if __name__ == "__main__":
main()
setup.py
ファイルには、ライブラリを Python ホイール ファイルにビルドするための追加の設定が含まれています。 <my-url>
、<my-author-name>@<my-organization>
および <my-package-description>
を意味のある値に置き換えます:
# Filename: setup.py
from setuptools import setup, find_packages
import dabdemo
setup(
name = "dabdemo",
version = dabdemo.__version__,
author = dabdemo.__author__,
url = "https://<my-url>",
author_email = "<my-author-name>@<my-organization>",
description = "<my-package-description>",
packages = find_packages(include = ["dabdemo"]),
entry_points={"group_1": "run=dabdemo.__main__:main"},
install_requires = ["setuptools"]
)
Python ホイールのコンポーネント ロジックをテストする
Run Unit Tests
ステージは、この Jenkins パイプラインの 4 番目のステージで、pytest
を使用してライブラリのロジックをテストして、ビルドどおりに動作することを確認します。 このステージは次のように定義されます。
stage('Run Unit Tests') {
sh """#!/bin/bash
${DBCLIPATH}/databricks bundle run -t ${BUNDLETARGET} run-unit-tests
"""
}
このステージでは、Databricks CLI を使用してノートブック ジョブを実行します。 このジョブでは、run-unit-test.py
というファイル名で Python ノートブックを実行します。 このノートブックは、ライブラリのロジックに対して pytest
が実行されます。
この例の単体テストを実行するには、ローカル コンピューター上の複製されたリポジトリのルートに次のコンテンツを含む run_unit_tests.py
という名前の Python ノートブック ファイルを追加します。
# Databricks notebook source
# COMMAND ----------
# MAGIC %sh
# MAGIC
# MAGIC mkdir -p "/Workspace${WORKSPACEBUNDLEPATH}/Validation/reports/junit/test-reports"
# COMMAND ----------
# Prepare to run pytest.
import sys, pytest, os
# Skip writing pyc files on a readonly filesystem.
sys.dont_write_bytecode = True
# Run pytest.
retcode = pytest.main(["--junit-xml", f"/Workspace{os.getenv('WORKSPACEBUNDLEPATH')}/Validation/reports/junit/test-reports/TEST-libout.xml",
f"/Workspace{os.getenv('WORKSPACEBUNDLEPATH')}/files/Libraries/python/dabdemo/dabdemo/"])
# Fail the cell execution if there are any test failures.
assert retcode == 0, "The pytest invocation failed. See the log for details."
ビルドされた Python ホイールを使用する
Run Notebook
というタイトルの Jenkins パイプラインの 5 番目のステージでは、次のように、ビルドされた Python ホイール ファイルでロジックを呼び出す Python ノートブックが実行されます。
stage('Run Notebook') {
sh """#!/bin/bash
${DBCLIPATH}/databricks bundle run -t ${BUNDLETARGET} run-dabdemo-notebook
"""
}
このステージでは、Databricks CLI を実行し、ワークスペースにノートブック ジョブを実行するように指示します。 このノートブックは、DataFrame オブジェクトを作成し、それをライブラリの with_status
関数に渡し、結果を出力して、ジョブの実行結果を報告します。 ローカル開発マシン上の複製されたリポジトリのルートに、次のコンテンツを含む dabdaddemo_notebook.py
という名前の Python ノートブック ファイルを追加して、ノートブックを作成します。
# Databricks notebook source
# COMMAND ----------
# Restart Python after installing the wheel.
dbutils.library.restartPython()
# COMMAND ----------
from dabdemo.addcol import with_status
df = (spark.createDataFrame(
schema = ["first_name", "last_name", "email"],
data = [
("paula", "white", "paula.white@example.com"),
("john", "baer", "john.baer@example.com")
]
))
new_df = with_status(df)
display(new_df)
# Expected output:
#
# +------------+-----------+-------------------------+---------+
# │first_name │last_name │email │status |
# +============+===========+=========================+=========+
# │paula │white │paula.white@example.com │checked |
# +------------+-----------+-------------------------+---------+
# │john │baer │john.baer@example.com │checked |
# +------------+-----------+-------------------------+---------+
ノートブック ジョブの実行結果を評価する
Evaluate Notebook Runs
ステージは、この Jenkins パイプラインの 6 番目のステージで、前のノートブック ジョブの実行結果を評価します。 このステージは次のように定義されます。
stage('Evaluate Notebook Runs') {
sh """#!/bin/bash
${DBCLIPATH}/databricks bundle run -t ${BUNDLETARGET} evaluate-notebook-runs
"""
}
このステージでは、Databricks CLI を実行し、ワークスペースに Python ファイル ジョブを実行するように指示します。 この Python ファイルは、ノートブック ジョブの実行の失敗と成功の条件を決定し、この失敗または成功の結果を報告します。 ローカル開発マシンの複製されたリポジトリのルートに、次のコンテンツを含む evaluate_notebook_runs.py
という名前のファイルを作成します。
import unittest
import xmlrunner
import json
import glob
import os
class TestJobOutput(unittest.TestCase):
test_output_path = f"/Workspace${os.getenv('WORKSPACEBUNDLEPATH')}/Validation/Output"
def test_performance(self):
path = self.test_output_path
statuses = []
for filename in glob.glob(os.path.join(path, '*.json')):
print('Evaluating: ' + filename)
with open(filename) as f:
data = json.load(f)
duration = data['tasks'][0]['execution_duration']
if duration > 100000:
status = 'FAILED'
else:
status = 'SUCCESS'
statuses.append(status)
f.close()
self.assertFalse('FAILED' in statuses)
def test_job_run(self):
path = self.test_output_path
statuses = []
for filename in glob.glob(os.path.join(path, '*.json')):
print('Evaluating: ' + filename)
with open(filename) as f:
data = json.load(f)
status = data['state']['result_state']
statuses.append(status)
f.close()
self.assertFalse('FAILED' in statuses)
if __name__ == '__main__':
unittest.main(
testRunner = xmlrunner.XMLTestRunner(
output = f"/Workspace${os.getenv('WORKSPACEBUNDLEPATH')}/Validation/Output/test-results",
),
failfast = False,
buffer = False,
catchbreak = False,
exit = False
)
テスト結果のインポートと報告
Import Test Results
というタイトルの Jenkins パイプラインの 7 番目のステージでは、Databricks CLI を使用して、ワークスペースからローカル開発マシンにテスト結果を送信します。 Publish Test Results
というタイトルの 8 番目と最後のステージでは、junit
Jenkins プラグインを使用してテスト結果を Jenkins に公開します。 これによって、テスト結果の状態に関するレポートとダッシュボードを視覚化できます。 これらのステージは次のように定義されます。
stage('Import Test Results') {
def DATABRICKS_BUNDLE_WORKSPACE_FILE_PATH
def getPath = "${DBCLIPATH}/databricks bundle validate -t ${BUNDLETARGET} | ${JQPATH}/jq -r .workspace.file_path"
def output = sh(script: getPath, returnStdout: true).trim()
if (output) {
DATABRICKS_BUNDLE_WORKSPACE_FILE_PATH = "${output}"
} else {
error "Failed to capture output or command execution failed: ${getPath}"
}
sh """#!/bin/bash
${DBCLIPATH}/databricks workspace export-dir \
${DATABRICKS_BUNDLE_WORKSPACE_FILE_PATH}/Validation/Output/test-results \
${WORKSPACE}/Validation/Output/test-results \
--overwrite
"""
}
stage('Publish Test Results') {
junit allowEmptyResults: true, testResults: '**/test-results/*.xml', skipPublishingChecks: true
}
すべてのコード変更をサードパーティのリポジトリにプッシュする
これにより、ローカル開発マシン上の複製されたリポジトリのコンテンツをサードパーティのリポジトリにプッシュする必要があります。 プッシュする前に、まず、複製されたリポジトリ内の .gitignore
ファイルに次のエントリを追加する必要があります。内部 Databricks アセット バンドルの作業ファイル、検証レポート、Python ビルド ファイル、Python キャッシュをサードパーティのリポジトリにプッシュしないようにする必要があります。 通常、古い可能性のある検証レポートと Python ホイール ビルドを使用するのではなく、Azure Databricks ワークスペースで新しい検証レポートと最新の Python ホイール ビルドを再生成する必要があります。
.databricks/
.vscode/
Libraries/python/dabdemo/build/
Libraries/python/dabdemo/__pycache__/
Libraries/python/dabdemo/dabdemo.egg-info/
Validation/
Jenkins パイプラインを実行する
これで、Jenkins パイプラインを手動で実行する準備ができました。 これを行うには、Jenkins ダッシュボードから次の手順を実行します。
- Jenkins パイプラインの名前をクリックします。
- サイドバーで、[今すぐビルド] をクリックします。
- 結果を表示するには、最新のパイプライン実行 (例:
#1
) をクリックし、[コンソール出力] をクリックします。
この時点で、CI/CD パイプラインでは統合とデプロイのサイクルが完了しています。 このプロセスを自動化することで、効率的で一貫性のある反復可能なプロセスによって、コードを確実にテストおよびデプロイできました。 リポジトリのプル要求など、特定のイベントが発生するたびに Jenkins を実行するようにサードパーティの Git プロバイダーに指示するには、サードパーティの Git プロバイダーのドキュメントを参照してください。