メインコンテンツまでスキップ

Databricks での Jenkins を使用した CI/CD

注記

この記事では、サードパーティによって開発された Jenkins について説明します。プロバイダーに問い合わせるには、 Jenkins ヘルプを参照してください。

この記事では、 Jenkins自動化サーバーを Databricks と組み合わせて使用し、CI/CD 開発ワークフローを実装する方法について説明します。

Databricks を使用した CI/CD の概要については、 「Databricks 上の CI/CD」を参照してください。ベスト プラクティスについては、 「Databricks のベスト プラクティスと推奨される CI/CD ワークフロー」を参照してください。

ローカル開発マシンのセットアップ

この記事の例では、Jenkinsを使用してDatabricks CLI宣言型自動化バンドルに以下の操作を実行させます。

  1. ローカルの開発マシンで Python wheel ファイルをビルドします。
  2. ビルドされた Python wheel ファイルを、追加の Python ファイルおよび Python ノートブックと共に、ローカル開発マシンから Databricks ワークスペースにデプロイします。
  3. アップロードした Python wheel ファイルとノートブックをそのワークスペースでテストして実行します。

この例のビルドとアップロードのステージを実行するように Databricks ワークスペースに指示するようにローカル開発マシンを設定するには、ローカル開発マシンで次の操作を行います。

ステップ 1: 必要なツールをインストールする

この手順では、 Databricks CLI、Jenkins、 jq、および Python wheel ビルド ツールをローカル開発マシンにインストールします。 この例を実行するには、これらのツールが必要です。

  1. Databricks CLI バージョン 0.205 以降をまだインストールしていない場合は、インストールします。Jenkins は Databricks CLI を使用して、この例のテストと実行の手順をワークスペースに渡します。「Databricks CLI のインストールまたは更新」を参照してください。

  2. Jenkins をまだインストールしていない場合は、インストールして起動します。LinuxmacOS またはWindows用の Jenkinsのインストール を参照してください。

  3. jqをインストールします。この例では、 jq を使用して JSON 形式のコマンド出力を解析します。

  4. pip を使用して、次のコマンドで Python wheel ビルドツールをインストールします (一部のシステムでは、pipの代わりに pip3 を使用する必要がある場合があります)。

    Bash
    pip install --upgrade wheel

ステップ 2: Jenkins パイプラインを作成する

この手順では、Jenkins を使用して、この記事の例の Jenkins パイプラインを作成します。Jenkins には、CI/CD パイプラインを作成するためのいくつかの異なるプロジェクトの種類が用意されています。Jenkins パイプラインは、 Groovy コードを使用して Jenkins プラグインを呼び出し、設定することで、Jenkins パイプラインのステージを定義するためのインターフェイスを提供します。

Jenkins プロジェクトの種類

Jenkins で Jenkins パイプラインを作成するには:

  1. Jenkins を起動したら、Jenkins ダッシュボード から [New Item (新規アイテム )] をクリックします。
  2. [ 項目名を入力してください ] に、Jenkins パイプラインの名前 ( jenkins-demoなど) を入力します。
  3. 「パイプライン」 プロジェクト・タイプ・アイコンをクリックします。
  4. [OK] をクリックします。Jenkins パイプラインの [設定] ページが表示されます。
  5. [ パイプライン] 領域の [ 定義 ] ドロップダウン リストで、[ SCM からのパイプライン スクリプト ] を選択します。
  6. [SCM ] ドロップダウン リストで、[ Git ] を選択します。
  7. [リポジトリ URL ] に、サードパーティの Git プロバイダーによってホストされているリポジトリの URL を入力します。
  8. [ブランチ指定子] に「*/<branch-name>」と入力します。ここで、<branch-name> は、使用するリポジトリ内のブランチの名前 (例: */mainです)。
  9. [ スクリプト パス ] に「 Jenkinsfile」と入力します (まだ設定されていない場合)。Jenkinsfileは、この記事の後半で作成します。
  10. [軽量チェックアウト ] というタイトルのボックスがすでにチェックされている場合は、チェックを外します。
  11. 保存 をクリックします。

ステップ 3: Jenkins にグローバル環境変数を追加する

このステップでは、3 つのグローバル環境変数を Jenkins に追加します。 Jenkins はこれらの環境変数を Databricks CLI に渡します。Databricks CLI では、Databricks ワークスペースに対して認証を行うために、これらの環境変数の値が必要です。この例では、サービスプリンシパルにOAuthマシン間 (M2M) 認証を使用します (ただし、他の認証タイプも使用できます)。 DatabricksワークスペースにOAuth M2M 認証を設定するには、 OAuthを使用してDatabricksへのサービスプリンシパル アクセスを承認する」を参照してください。

この例の 3 つのグローバル環境変数は次のとおりです。

  • DATABRICKS_HOSTで、 https://で始まる Databricks ワークスペース URL に設定します。ワークスペースインスタンス名、URL、ID を参照してください。
  • DATABRICKS_CLIENT_IDは、サービスプリンシパルのクライアント ID (アプリケーション ID とも呼ばれる) に設定します。
  • DATABRICKS_CLIENT_SECRETで、サービスプリンシパルの Databricks OAuth シークレットに設定します。

Jenkins でグローバル環境変数を設定するには、Jenkins ダッシュボード から次の操作を行います。

  1. サイドバーで、「 Jenkinsを管理 」をクリックします。
  2. [システム構成 ] セクションで、[ システム ] をクリックします。
  3. [グローバル プロパティ] セクションで、 [環境変数] というタイトルのボックスをオンにします。
  4. [追加 ] をクリックし、環境変数 の [名前 ] と [値 ] を入力します。追加の環境変数ごとにこれを繰り返します。
  5. 環境変数の追加が完了したら、 「保存」 をクリックして Jenkins ダッシュボード に戻ります。

Jenkins パイプラインの設計

Jenkins には、CI/CD パイプラインを作成するためのいくつかの異なるプロジェクトの種類が用意されています。この例では、Jenkins パイプラインを実装します。Jenkins パイプラインは、 Groovy コードを使用して Jenkins プラグインを呼び出し、設定することで、Jenkins パイプラインのステージを定義するためのインターフェイスを提供します。

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> を文字列に置き換えて、この例のワークスペースで作成されたジョブを一意に識別できるようにします。たとえば、これは jenkins-demoです。
  • BUNDLETARGETdevに設定されていることに注意してください。これは、この記事の後半で定義される Declarative Automation Bundles ターゲットの名前です。実際のシステム実装では、これを独自のバンドルターゲットの名前に変更してください。バンドルターゲットに関する詳細は、この記事の後半で説明します。

リポジトリのルートに追加する必要がある Jenkinsfileを次に示します。

Groovy
// 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 ステージは、次のように定義されます。

Groovy
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 ステージは、次のように定義されます。

Groovy
stage('Validate Bundle') {
sh """#!/bin/bash
${DBCLIPATH}/databricks bundle validate -t ${BUNDLETARGET}
"""
}

この段階では、アーティファクトをテストおよび実行するためのワークフローを定義するバンドルが構文的に正しいことを確認します。 宣言的オートメーション バンドルを使用すると、完全なデータ分析とMLプロジェクトをソース ファイルのコレクションとして表現できます。 「宣言型自動化バンドルとは何か?」を参照してください。

この記事のバンドルを定義するには、ローカル コンピューター上のクローンされたリポジトリのルートに databricks.yml という名前のファイルを作成します。この例 databricks.yml ファイルでは、次のプレースホルダーを置き換えます。

  • <bundle-name> をバンドルの一意のプログラム名に置き換えます。たとえば、これは jenkins-demoです。
  • <job-prefix-name> を文字列に置き換えて、この例のワークスペースで作成されたジョブを一意に識別できるようにします。たとえば、これは jenkins-demoです。Jenkinsfile の JOBPREFIX 値と一致する必要があります。
  • <spark-version-id> を、ジョブ クラスターの Databricks Runtime バージョン ID (13.3.x-scala2.12 など) に置き換えます。
  • <cluster-node-type-id> をジョブ クラスターのノード タイプ ID に置き換えます (例: i3.xlarge)。
  • targetsマッピングのdevは、Jenkinsfile のBUNDLETARGETと同じであることに注意してください。バンドル・ターゲットは、ホストおよび関連するデプロイメント動作を指定します。

以下は、この例が正しく動作するためにリポジトリのルートに追加する必要がある databricks.yml ファイルです。

YAML
# 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ファイルの詳細については、 「宣言的オートメーション バンドルの構成」を参照してください。

バンドルをワークスペースにデプロイする

ジェンキンス・パイプラインの第3段階は、 Deploy Bundleと題され、次のように定義されています。

Groovy
stage('Deploy Bundle') {
sh """#!/bin/bash
${DBCLIPATH}/databricks bundle deploy -t ${BUNDLETARGET}
"""
}

このステージでは、次の 2 つのことを行います。

  1. ファイルの マッピングがartifact databricks.yml``whlDatabricksCLIPython wheelに設定されているため、指定したロケーションのsetup.py ファイルを使用して ファイルをビルドするように に指示します。
  2. Python wheelファイルがローカル開発マシン上にビルドされると、 Databricks CLI 、ビルドされたPython wheelファイルを、指定されたPythonファイルおよびノートブックとともにDatabricksワークスペースにデプロイします。 安心までに、Declarative Automation Bundles はPython wheelファイルとその他のファイルを/Workspace/Users/<your-username>/.bundle/<bundle-name>/<target-name>にデプロイします。

Python wheel ファイルを databricks.yml ファイルで指定されたとおりにビルドできるようにするには、ローカル マシン上のクローン リポジトリのルートに次のフォルダーとファイルを作成します。

ノートブックが実行するPython wheelファイルのロジックと単体テストを定義するには、 addcol.pytest_addcol.pyという名前の 2 つのファイルを作成し、リポジトリのLibrariesフォルダー内のpython/dabdemo/dabdemoという名前のフォルダー構造に追加します。

├── ...
├── Libraries
│ └── python
│ └── dabdemo
│ └── dabdemo
│ ├── addcol.py
│ └── test_addcol.py
├── ...

addcol.pyファイルには、後でPython wheelファイルに構築され、 Databricksクラスターにインストールされるライブラリ関数が含まれています。 この関数は、リテラルが設定された新しい列を Apache Spark DataFrame に追加します。

Python
# Filename: addcol.py
import pyspark.sql.functions as F

def with_status(df):
return df.withColumn("status", F.lit("checked"))

test_addcol.pyファイルには、モックデータフレームオブジェクトをwith_status関数に渡すためのテストが含まれています。これは、addcol.py定義されています。ザ 次に、result が、予期される値を含む データフレーム オブジェクトと比較されます。 値が一致する場合 (この場合は一致します)、テストは成功します。

Python
# 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 wheelファイルに正しくパッケージ化できるようにするには、前の 2 つのファイルと同じフォルダーに__init__.py__main__.pyという名前の 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>を自分の名前に置き換えます。

Python
# 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ファイルには、ライブラリのエントリポイントが含まれています。

Python
# 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 wheelファイルにビルドするための追加設定が含まれています。<my-url><my-author-name>@<my-organization>、および <my-package-description> を意味のある値に置き換えます。

Python
# 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 wheelのコンポーネント ロジックをテストする

この Jenkins パイプラインの 4 番目のステージである Run Unit Tests ステージでは、 pytest を使用してライブラリのロジックをテストし、ビルドどおりに動作することを確認します。このステージは、次のように定義されます。

Groovy
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 ノートブック ファイルを、ローカル マシン上のクローン リポジトリのルートに追加します。

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 wheelを使用する

この Jenkins パイプラインの 5 番目のステージ ( Run Notebookと題されている) では、次のように、ビルドされた Python wheel ファイル内のロジックを呼び出す Python ノートブックが実行されます。

Groovy
stage('Run Notebook') {
sh """#!/bin/bash
${DBCLIPATH}/databricks bundle run -t ${BUNDLETARGET} run-dabdemo-notebook
"""
}

このステージでは、 Databricks CLIが実行され、ノートブック ジョブを実行するようにワークスペースに指示します。 このノートブックは、DataFrame オブジェクトを作成し、ライブラリの with_status 関数に渡し、結果を出力して、ジョブの実行結果を報告します。ノートブックを作成するには、 dabdaddemo_notebook.py という名前の Python ノートブック ファイルを、次の内容で、ローカル開発マシン上のクローン リポジトリのルートに追加します。

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 |
# +------------+-----------+-------------------------+---------+

ノートブック ジョブの実行結果を評価する

この Jenkins パイプラインの 6 番目のステージである Evaluate Notebook Runs ステージでは、前のノートブック ジョブの実行結果が評価されます。このステージは、次のように定義されます。

Groovy
stage('Evaluate Notebook Runs') {
sh """#!/bin/bash
${DBCLIPATH}/databricks bundle run -t ${BUNDLETARGET} evaluate-notebook-runs
"""
}

このステージでは、 Databricks CLIが実行され、ワークスペースに Python ファイル ジョブを実行するように指示します。 この Python ファイルは、ノートブック ジョブの実行の失敗と成功の基準を決定し、この失敗または成功の結果を報告します。次の内容を含む evaluate_notebook_runs.py という名前のファイルを、ローカル開発マシンのクローンされたリポジトリのルートに作成します。

Python
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
)

テスト結果のインポートとレポート

この Jenkins パイプラインの 7 番目のステージ ( Import Test Resultsという名前) では、Databricks CLI を使用して、ワークスペースからローカルの開発マシンにテスト結果を送信します。Publish Test Resultsというタイトルの 8 番目の最終ステージでは、junit Jenkins プラグインを使用してテスト結果を Jenkins に公開します。これにより、テスト結果のステータスに関連するレポートとダッシュボードを視覚化できます。これらのステージは、次のように定義されます。

Groovy
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
}

Jenkinsテスト結果

すべてのコード変更をサードパーティのリポジトリにプッシュする

これで、ローカル開発マシン上のクローンしたリポジトリの内容を、サードパーティのリポジトリにプッシュする必要があります。プッシュする前に、クローンしたリポジトリの.gitignoreファイルに次のエントリを追加する必要があります。内部バンドル作業ファイル、検証レポート、Python ビルドファイル、および Python キャッシュをサードパーティのリポジトリにプッシュすべきではないためです。通常、古い可能性のある検証レポートとPython wheelを使用する代わりに、新しい検証レポートと最新のPython wheelを再生成してDatabricksワークスペースに組み込む必要があります。

.databricks/
.vscode/
Libraries/python/dabdemo/build/
Libraries/python/dabdemo/__pycache__/
Libraries/python/dabdemo/dabdemo.egg-info/
Validation/

実行 your Jenkins パイプライン

これで、Jenkins パイプラインを手動で実行する準備が整いました。これを行うには、Jenkins ダッシュボード から次の手順を実行します。

  1. Jenkins パイプラインの名前をクリックします。
  2. サイドバーで、[ 今すぐビルド ] をクリックします。
  3. 結果を表示するには、最新のパイプライン実行( #1など)をクリックし、[ コンソール出力 ]をクリックします。

この時点で、CI/CD パイプラインは統合とデプロイのサイクルを完了しています。このプロセスを自動化することで、効率的で一貫性があり、反復可能なプロセスによってコードがテストおよびデプロイされていることを確認できます。リポジトリのプルリクエストなど、特定のイベントが発生するたびにJenkinsを実行するようにサードパーティのGitプロバイダーに指示するには、サードパーティのGitプロバイダーのドキュメントを参照してください。