笔记本的软件工程最佳做法

本文提供了一个动手演练,演示如何将软件工程最佳做法应用于 Azure Databricks 笔记本,包括版本控制、代码共享、测试和(可选)持续集成和持续交付或部署 (CI/CD)。

本演练中的操作:

  • 将笔记本添加到 Azure Databricks Git 文件夹进行版本控制。
  • 将某个笔记本中的部分代码提取到可共享模块中。
  • 测试共享代码。
  • 从 Azure Databricks 作业运行笔记本。
  • (可选)将 CI/CD 应用于共享代码。

要求

要完成本演练,必须提供以下资源:

  • 具有 Databricks 支持的 Git 提供程序的远程存储库。 本文演练使用的是 GitHub。 本演练假定你有名为 best-notebooks 的可用 GitHub 存储库。 (可为存储库指定其他名称。如果这样做,请在本演练中将 best-notebooks 替换为存储库的名称。)请创建一个 GitHub 存储库(如果尚未创建)。

    注意

    如果创建新存储库,请务必使用至少一个文件(例如 README 文件)初始化存储库。

  • 一个 Azure Databricks 工作区。 如果还没有工作区,请创建一个

  • 工作区中的 Azure Databricks 通用群集。 要在设计阶段运行笔记本,可将笔记本附加到正在运行的通用群集。 稍后,本演练使用 Azure Databricks 作业使运行此群集上的笔记本变得自动化。 (还可在仅存在于作业生存期的作业群集上运行作业。)如果还没有通用群集,则创建通用群集

步骤 1:设置 Databricks Git 文件夹

此步骤中,将现有 GitHub 存储库连接到现有 Azure Databricks 工作区中的 Azure Databricks Git 文件夹。

要使工作区能够连接到 GitHub 存储库,必须先向工作区提供 GitHub 凭据(如果尚未这样做)。

步骤 1.1:提供 GitHub 凭据

  1. 在工作区右上角单击你的用户名,然后在下拉列表中单击“设置”
  2. 在“设置”边栏的“用户”下,点击“链接帐户”
  3. 在“Git 集成”下,对于“Git 提供程序”,请选择“GitHub”。
  4. 单击 个人访问令牌
  5. 对于“Git 提供程序用户名或电子邮件”,请输入 GitHub 用户名。
  6. 为“令牌”输入你的 GitHub 个人访问令牌。 此个人访问令牌(经典)必须具有存储库和工作流权限。
  7. 单击“ 保存”。

步骤 1.2:连接到 GitHub 存储库

  1. 在工作区边栏上,点击“工作区”
  2. 在“工作区”浏览器中,展开“工作区”>“用户”
  3. 右键单击用户名文件夹,然后单击“创建”>“Git 文件夹”
  4. 在“创建 Git 文件夹”对话框中
    1. 对于“Git 存储库 URL”,请输入 GitHub 存储库的 GitHub 使用 HTTPS 进行克隆 URL。 本文假定 URL 以 best-notebooks.git 结尾,例如 https://github.com/<your-GitHub-username>/best-notebooks.git
    2. 对于“Git 提供程序”,请选择“GitHub”。
    3. 将“Git 文件夹名称”设为你的存储库的名称,例如 best-notebooks
    4. 单击“创建 Git 文件夹”

步骤 2:导入并运行笔记本

在此步骤中,将现有外部笔记本导入存储库。 可以为本演练创建自己的笔记本,但为了加快速度,我们在此处为你提供了笔记本。

步骤 2.1:在存储库中创建工作分支

此子步骤中,将在存储库中创建名为 eda 的分支。 通过此分支,可以独立于存储库的 main 分支来处理文件和代码,这是软件工程最佳做法。 (可为分支提供其他名称。)

注意

在某些存储库中,可以改为将 main 分支命名为 master。 如果这样做,请在本演练中将 main 替换为 master

提示

如果不熟悉使用 Git 分支,请参阅 Git 网站上的 Git 分支 - Nutshell 中的分支

  1. 应会打开步骤 1.2 中的 Git 文件夹。 如果没有打开,请在“工作区”边栏中展开“工作区”>“用户”,然后展开用户名文件夹,单击 Git 文件夹

  2. 在工作区导航痕迹下的文件夹名称旁边,单击“主 Git 分支”按钮

  3. 在“best-notebooks”对话框中点击“创建分支”按钮

    注意

    如果存储库的名称不是 best-notebooks,则在此处和演练的其他地方该对话框的标题将有所不同。

  4. 输入eda并点击“创建”

  5. 关闭此对话框。

步骤 2.2:将笔记本导入存储库

在此子步骤中,将现有笔记本从另一个存储库导入你的存储库。 此笔记本执行以下操作:

  • 将 CSV 文件从 owid/covid-19-data GitHub 存储库复制到工作区中的群集。 此 CSV 文件包含有关全球 COVID-19 住院和重症监护指标的公共数据。
  • 将 CSV 文件的内容读入 pandas DataFrame
  • 筛选数据以仅包含来自美国的指标。
  • 显示数据的绘图。
  • 将 pandas DataFrame 另存为 Spark 上的 Pandas API DataFrame
  • 对“Spark 上的 Pandas API”数据帧执行数据清理。
  • 将 Spark 上 Pandas API DataFrame 以 Delta 表形式写入工作区。
  • 显示 Delta 表的内容。

虽然可在存储库中创建自己的笔记本,但在此导入现有笔记本有助于加快本演练的进度。 若要在此分支中创建笔记本或将现有笔记本移入此分支而不是导入笔记本,请参阅工作区文件基本用法

  1. 在“best-notebooks”Git 文件夹中,单击“创建”>“文件夹”
  2. 在“新建文件夹”对话框中输入 notebooks,然后单击“创建”
  3. 在“笔记本”文件夹中,单击三个点,然后单击“导入”
  4. 在“导入”对话框中
    1. 对于“导入自”,请选择“URL”。

    2. 在 GitHub 中的 databricks/notebook-best-practices 存储库中输入 covid_eda_raw 笔记本原始内容的 URL。 要获取此 URL,请执行以下步骤:i. 转到 https://github.com/databricks/notebook-best-practices 。 ii. 单击 notebooks 文件夹。 iii. 单击 covid_eda_raw.py 文件。 iv. 单击“原始”。 .v 将 Web 浏览器地址栏中的完整 URL 复制到 “导入”对话框

      注意

      “导入”对话框仅适用于公共存储库的 Git URL

    3. 单击“导入” 。

步骤 2.3:运行笔记本

  1. 如果笔记本尚未显示,请打开“笔记本”文件夹,然后单击文件夹内的“covid_eda_raw”笔记本
  2. 选择要将此笔记本附加到的群集。 有关创建群集的说明,请参阅创建群集
  3. 单击“全部运行”。
  4. 等待笔记本运行。

笔记本运行完成后,你应会在笔记本中看到数据的绘图以及 Delta 表中超过 600 行的原始数据。 如果你在开始运行此笔记本时群集尚未运行,群集可能需要几分钟才能启动,然后才能显示结果。

步骤 2.4:签入和合并笔记本

此子步骤中,到目前为止都将工作保存到 GitHub 存储库。 然后将笔记本从工作分支合并到存储库的 main 分支。

  1. 在笔记本的名称旁边,单击“eda”Git 分支按钮。
  2. 在 best-notebooks 对话框中的“更改”选项卡上,确保已选中 notebooks/covid_eda_raw.py 文件。
  3. 对于“提交消息(必填)”,请输入 Added raw notebook
  4. 对于“说明”(可选),请输入 This is the first version of the notebook.
  5. 单击“提交和推送”。
  6. 单击横幅中“在 git 提供程序上创建拉取请求”中的拉取请求链接
  7. 在 GitHub 中创建拉取请求,然后将拉取请求合并到 main 分支。
  8. 返回 Azure Databricks 工作区,如果 best-notebooks 对话框仍然显示,请将其关闭。

步骤 3:将代码移到共享模块中

在此步骤中,将笔记本中的部分代码移到笔记本外部的一组共享函数中。 这样做可将这些函数与其他类似的笔记本配合使用,从而加快将来的编码速度,并帮助确保笔记本结果更加可预测且更一致。 共享此代码还使你能够更轻松地测试这些函数,这作为软件工程最佳做法,可以提高代码的整体质量。

步骤 3.1:在存储库中创建其他工作分支

  1. 在笔记本的名称旁边,单击“eda”Git 分支按钮。
  2. 在“best-notebooks”对话框中,单击“eda”分支旁的下拉箭头,然后选择“主要”
  3. 单击“拉取”按钮。 如果系统提示继续拉取,请单击“确认”。
  4. 单击“创建分支”按钮
  5. 输入 first_modules,然后单击“创建”。 (可为分支提供其他名称。)
  6. 关闭此对话框。

步骤 3.2:将笔记本导入存储库

要加快本演练的速度,在此子步骤中,将另一个现有笔记本导入存储库。 此笔记本与上一个笔记本执行相同的操作,但此笔记本将调用存储在笔记本外部的共享代码函数。 同样,你可在此处的存储库中创建自己的笔记本,并自行执行实际代码共享。

  1. 在“工作区”浏览器中,右键单击“笔记本”文件夹,然后单击“导入”
  2. 在“导入”对话框中
    1. 对于“导入自”,请选择“URL”。

    2. 在 GitHub 中的 databricks/notebook-best-practices 存储库中输入 covid_eda_modular 笔记本原始内容的 URL。 要获取此 URL,请执行以下步骤:i. 转到 https://github.com/databricks/notebook-best-practices 。 ii. 单击 notebooks 文件夹。 iii. 单击 covid_eda_modular.py 文件。 iv. 单击“原始”。 v. 将 Web 浏览器地址栏中的完整 URL 复制到 “导入笔记本”对话框。

      注意

      “导入笔记本”对话框仅适用于公共存储库的 Git URL。

    3. 单击“导入” 。

步骤 3.3:添加笔记本的支持性共享代码函数

  1. 在“工作区”浏览器中,右键单击“best-notebooks”Git 文件夹,然后单击“创建”>“文件夹”

  2. 在“新建文件夹”对话框中输入 covid_analysis,然后单击“创建”

  3. 在 covid_analysis 文件夹中,单击“创建”>“文件”

  4. 在“新文件名称”对话框中输入 transforms.py,然后单击“创建文件”。

  5. 在 transforms.py 编辑器窗口中输入以下代码:

    import pandas as pd
    
    # Filter by country code.
    def filter_country(pdf, country="USA"):
      pdf = pdf[pdf.iso_code == country]
      return pdf
    
    # Pivot by indicator, and fill missing values.
    def pivot_and_clean(pdf, fillna):
      pdf["value"] = pd.to_numeric(pdf["value"])
      pdf = pdf.fillna(fillna).pivot_table(
        values="value", columns="indicator", index="date"
      )
      return pdf
    
    # Create column names that are compatible with Delta tables.
    def clean_spark_cols(pdf):
      pdf.columns = pdf.columns.str.replace(" ", "_")
      return pdf
    
    # Convert index to column (works with pandas API on Spark, too).
    def index_to_col(df, colname):
      df[colname] = df.index
      return df
    

提示

有关其他代码共享技术,请参阅在 Databricks 笔记本之间共享代码

步骤 3.4:添加共享代码的依赖项

前面的代码具有多个 Python 包依赖项,使代码能够正常运行。 在此子步骤中,你将声明这些包依赖项。 声明依赖项通过使用精确定义的库版本来提高可再现性。

  1. 在“工作区”浏览器中,右键单击“best-notebooks”Git 文件夹,然后单击“创建”>“文件”

    注意

    你希望列有包依赖项的文件进入 Git 文件夹的根目录而不是 notebooks 或 covid_analysis 文件夹。

  2. 在“新文件名称”对话框中输入 requirements.txt,然后单击“创建文件”。

  3. 在 requirements.txt 编辑器窗口中,输入以下代码

    注意

    如果 requirements.txt 文件不可见,可能需要刷新 Web 浏览器。

    -i https://pypi.org/simple
    attrs==21.4.0
    cycler==0.11.0
    fonttools==4.33.3
    iniconfig==1.1.1
    kiwisolver==1.4.2
    matplotlib==3.5.1
    numpy==1.22.3
    packaging==21.3
    pandas==1.4.2
    pillow==9.1.0
    pluggy==1.0.0
    py==1.11.0
    py4j==0.10.9.3
    pyarrow==7.0.0
    pyparsing==3.0.8
    pyspark==3.2.1
    pytest==7.1.2
    python-dateutil==2.8.2
    pytz==2022.1
    six==1.16.0
    tomli==2.0.1
    wget==3.2
    

    注意

    上述文件列出了特定的包版本。 为了获得更好的兼容性,可以将这些版本与安装在通用群集上的版本进行交叉引用。 请参阅 Databricks Runtime 发行说明版本和兼容性中的“系统环境”部分,了解群集的 Databricks Runtime 版本。

存储库结构现应如下所示:

|-- covid_analysis
│  └── transforms.py
├── notebooks
│  ├── covid_eda_modular
│  └── covid_eda_raw (optional)
└── requirements.txt

步骤 3.5:运行重构的笔记本

在此子步骤中,你将运行 covid_eda_modular 笔记本,该笔记本将调用 covid_analysis/transforms.py 中的共享代码。

  1. 在“工作区”浏览器中,单击“笔记本”文件夹中的“covid_eda_modular”笔记本
  2. 选择要将此笔记本附加到的群集
  3. 单击“全部运行”。
  4. 等待笔记本运行。

笔记本运行完成后,你应会在笔记本中看到与 covid_eda_raw 笔记本相似的结果:数据绘图以及 Delta 表中超过 600 行的原始数据。 与此笔记本的主要区别在于使用了不同的筛选器(DZAiso_code 而不是 USA)。 如果你在开始运行此笔记本时群集尚未运行,群集可能需要几分钟才能启动,然后才能显示结果。

  1. 在笔记本的名称旁边,单击“ first_modules”Git 分支按钮。
  2. 在“best-notebooks”对话框的“更改”选项卡上,确保已选择以下内容
    • requirements.txt
    • covid_analysis/transforms.py
    • notebooks/covid_eda_modular.py
  3. 对于“提交消息(必填)”,请输入 Added refactored notebook
  4. 对于“说明”(可选),请输入 This is the second version of the notebook.
  5. 单击“提交和推送”。
  6. 单击横幅中“在 git 提供程序上创建拉取请求”中的拉取请求链接
  7. 在 GitHub 中创建拉取请求,然后将拉取请求合并到 main 分支。
  8. 返回 Azure Databricks 工作区,如果 best-notebooks 对话框仍然显示,请将其关闭。

步骤 4:测试共享代码

在此步骤中,你将测试上一步中的共享代码。 但是,你希望在不运行 covid_eda_modular 笔记本本身的情况下测试此代码。 这是因为如果共享代码无法运行,笔记本本身也可能无法运行。 你希望在主笔记本最终出现故障之前,先捕获共享代码中的故障。 此测试技术是软件工程最佳做法。

提示

有关笔记本测试以及 R 和 Scala 笔记本测试的其他方法,请参阅笔记本单元测试

步骤 4.1:在存储库中创建其他工作分支

  1. 在笔记本的名称旁边,单击“ first_modules”Git 分支按钮。
  2. 在“best-notebooks”对话框中,单击“first_modules”分支旁的下拉箭头,然后选择“主要”
  3. 单击“拉取”按钮。 如果系统提示继续拉取,请单击“确认”。
  4. 单击“创建分支”。
  5. 输入 first_tests,然后单击“创建”。 (可为分支提供其他名称。)
  6. 关闭此对话框。

步骤 4.2:添加测试

在此子步骤中,使用 pytest 框架测试共享代码。 在这些测试中,断言是否实现了特定的测试结果。 如果任一测试产生意外结果,则该测试未能通过断言,因此测试本身也失败。

  1. 在“工作区”浏览器中,右键单击 Git 文件夹,然后单击“创建”>“文件夹”

  2. 在“新建文件夹”对话框中输入 tests,然后单击“创建”

  3. 在“测试”文件夹中,单击“创建”>“文件”

  4. 在“新文件名称”对话框中输入 testdata.csv,然后单击“创建文件”。

  5. 在 testdata.csv 编辑器窗口中输入以下测试数据

    entity,iso_code,date,indicator,value
    United States,USA,2022-04-17,Daily ICU occupancy,
    United States,USA,2022-04-17,Daily ICU occupancy per million,4.1
    United States,USA,2022-04-17,Daily hospital occupancy,10000
    United States,USA,2022-04-17,Daily hospital occupancy per million,30.3
    United States,USA,2022-04-17,Weekly new hospital admissions,11000
    United States,USA,2022-04-17,Weekly new hospital admissions per million,32.8
    Algeria,DZA,2022-04-18,Daily ICU occupancy,1010
    Algeria,DZA,2022-04-18,Daily ICU occupancy per million,4.5
    Algeria,DZA,2022-04-18,Daily hospital occupancy,11000
    Algeria,DZA,2022-04-18,Daily hospital occupancy per million,30.9
    Algeria,DZA,2022-04-18,Weekly new hospital admissions,10000
    Algeria,DZA,2022-04-18,Weekly new hospital admissions per million,32.1
    
  6. 在“测试”文件夹中,单击“创建”>“文件”

  7. 在“新文件名称”对话框中输入 transforms_test.py,然后单击“创建文件”。

  8. 在 transforms_test.py 编辑器窗口中,输入以下测试代码。 这些测试使用标准 pytest 固定例程以及模拟的内存中 pandas DataFrame:

    # Test each of the transform functions.
    import pytest
    from textwrap import fill
    import os
    import pandas as pd
    import numpy as np
    from covid_analysis.transforms import *
    from pyspark.sql import SparkSession
    
    @pytest.fixture
    def raw_input_df() -> pd.DataFrame:
      """
      Create a basic version of the input dataset for testing, including NaNs.
      """
      return pd.read_csv('tests/testdata.csv')
    
    @pytest.fixture
    def colnames_df() -> pd.DataFrame:
      df = pd.DataFrame(
        data=[[0,1,2,3,4,5]],
        columns=[
          "Daily ICU occupancy",
          "Daily ICU occupancy per million",
          "Daily hospital occupancy",
          "Daily hospital occupancy per million",
          "Weekly new hospital admissions",
          "Weekly new hospital admissions per million"
        ]
      )
      return df
    
    # Make sure the filter works as expected.
    def test_filter(raw_input_df):
      filtered = filter_country(raw_input_df)
      assert filtered.iso_code.drop_duplicates()[0] == "USA"
    
    # The test data has NaNs for Daily ICU occupancy; this should get filled to 0.
    def test_pivot(raw_input_df):
      pivoted = pivot_and_clean(raw_input_df, 0)
      assert pivoted["Daily ICU occupancy"][0] == 0
    
    # Test column cleaning.
    def test_clean_cols(colnames_df):
      cleaned = clean_spark_cols(colnames_df)
      cols_w_spaces = cleaned.filter(regex=(" "))
      assert cols_w_spaces.empty == True
    
    # Test column creation from index.
    def test_index_to_col(raw_input_df):
      raw_input_df["col_from_index"] = raw_input_df.index
      assert (raw_input_df.index == raw_input_df.col_from_index).all()
    

存储库结构现应如下所示:

├── covid_analysis
│  └── transforms.py
├── notebooks
│  ├── covid_eda_modular
│  └── covid_eda_raw (optional)
├── requirements.txt
└── tests
    ├── testdata.csv
    └── transforms_test.py

步骤 4.3:运行测试

若要加快本演练的进度,可在此子步骤中使用导入的笔记本来运行前面的测试。 此笔记本下载测试的依赖 Python 包并将其安装到工作区、运行测试并报告测试的结果。 虽然可从群集的 Web 终端运行 pytest,但从笔记本运行 pytest 可能会更方便。

注意

如果运行 pytest,将运行当前目录及其子目录中名称遵循 test_*.py/*_test.py 形式的所有文件。

  1. 在“工作区”浏览器中,右键单击“笔记本”文件夹,然后单击“导入”
  2. 在“导入笔记本”对话框中执行以下操作
    1. 对于“导入自”,请选择“URL”。

    2. 在 GitHub 中的 databricks/notebook-best-practices 存储库中输入 run_unit_tests 笔记本原始内容的 URL。 要获取此 URL,请执行以下步骤:i. 转到 https://github.com/databricks/notebook-best-practices 。 ii. 单击 notebooks 文件夹。 iii. 单击 run_unit_tests.py 文件。 iv. 单击“原始”。 v. 将 Web 浏览器地址栏中的完整 URL 复制到 “导入笔记本”对话框。

      注意

      “导入笔记本”对话框仅适用于公共存储库的 Git URL。

    3. 单击“导入” 。

  3. 选择要将此笔记本附加到的群集
  4. 单击“全部运行”。
  5. 等待笔记本运行。

笔记本运行完成后,你应会在笔记本中看到有关测试通过或失败次数的信息,以及其他相关详细信息。 如果你在开始运行此笔记本时群集尚未运行,群集可能需要几分钟才能启动,然后才能显示结果。

存储库结构现应如下所示:

├── covid_analysis
│  └── transforms.py
├── notebooks
│  ├── covid_eda_modular
│  ├── covid_eda_raw (optional)
│  └── run_unit_tests
├── requirements.txt
└── tests
    ├── testdata.csv
    └── transforms_test.py
  1. 在笔记本名称旁边,单击“first_tests”Git 分支按钮。
  2. 在“best-notebooks”对话框的“更改”选项卡上,确保已选择以下内容
    • tests/transforms_test.py
    • notebooks/run_unit_tests.py
    • tests/testdata.csv
  3. 对于“提交消息(必填)”,请输入 Added tests
  4. 对于“说明(可选)”,请输入 These are the unit tests for the shared code.
  5. 单击“提交和推送”。
  6. 单击横幅中“在 git 提供程序上创建拉取请求”中的拉取请求链接
  7. 在 GitHub 中创建拉取请求,然后将拉取请求合并到 main 分支。
  8. 返回 Azure Databricks 工作区,如果 best-notebooks 对话框仍然显示,请将其关闭。

步骤 5:创建作业以运行笔记本

在前面的步骤中,你手动测试了共享代码,并手动运行了笔记本。 在此步骤中,你将使用 Azure Databricks 作业来测试共享代码并自动运行笔记本(按需或定期运行)。

步骤 5.1:创建作业任务以运行测试笔记本

  1. 在工作区边栏上,点击“工作流”
  2. 在“作业”选项卡上单击“创建作业”。
  3. 将作业名称编辑为 covid_report
  4. 对于“任务名称”,请输入 run_notebook_tests
  5. 对于“类型”,请选择“笔记本”。
  6. 对于“源”,选择“Git 提供程序”
  7. 单击“添加 git 引用”。
  8. 在“Git 信息”对话框中执行以下操作
    1. 对于“Git 存储库 URL”,请输入 GitHub 存储库的 GitHub 使用 HTTPS 进行克隆 URL。 本文假定 URL 以 best-notebooks.git 结尾,例如 https://github.com/<your-GitHub-username>/best-notebooks.git
    2. 对于“Git 提供程序”,请选择“GitHub”。
    3. 对于“Git 引用(分支/标记/提交)”,请输入 main
    4. 在“Git 引用(分支/标记/提交)”旁边,请选择“分支”。
    5. 单击“确认” 。
  9. 对于“路径”,请输入 notebooks/run_unit_tests。 不要添加 .py 文件扩展名。
  10. 对于“群集”,请选择上一步中的群集。
  11. 单击“创建任务”。

注意

在这种情况下,Databricks 不建议使用笔记本中的计划按钮(如创建和管理计划的笔记本作业中所述)来计划作业以定期运行此笔记本。 这是因为计划按钮会使用工作区存储库中笔记本的最新工作副本来创建作业。 但 Databricks 建议你按照上述说明创建作业,使其使用存储库中笔记本的最新提交版本。

步骤 5.2:创建作业任务以运行主笔记本

  1. 单击“+ 添加任务”图标。
  2. 此时将显示一个弹出菜单。 选择“笔记本”。
  3. 对于“任务名称”,请输入 run_main_notebook
  4. 对于“类型”,请选择“笔记本”。
  5. 对于“路径”,请输入 notebooks/covid_eda_modular。 不要添加 .py 文件扩展名。
  6. 对于“群集”,请选择上一步中的群集。
  7. 验证“取决于”值是否为 run_notebook-tests
  8. 单击“创建任务”。

步骤 5.3 运行作业

  1. 单击“立即运行”。

  2. 在弹出窗口中,单击“查看运行”。

    注意

    如果弹出窗口消失得太快,请执行以下操作:

    1. 在边栏上的“数据科学与工程”或“Databricks 机器学习”环境中单击“工作流”
    2. 在“作业运行”选项卡上,单击“作业”列中具有 covid_report 的最新作业的“开始时间”值。
  3. 要查看作业结果,请单击 run_notebook_tests 磁贴和/或 run_main_notebook 磁贴。 每个磁贴上的结果与你自己逐个运行这些笔记本的结果相同。

注意

此作业按需运行。 若要设置此作业以定期运行,请参阅 Databricks 作业的触发器类型

(可选)步骤 6:设置存储库以测试代码并在代码发生更改时自动运行笔记本

在上一步中,你使用作业自动测试共享代码,并在某个时间点或定期运行笔记本。 但当更改合并到 GitHub 存储库时,你可能更希望使用 CI/CD 工具(例如,GitHub Actions)自动触发测试。

步骤 6.1:设置 GitHub 对工作区的访问权限

此子步骤中,将设置 GitHub Actions 工作流,每当更改合并到存储库中时该工作流在工作区中运行作业。 为此,请为 GitHub 提供唯一的 Azure Databricks 令牌进行访问。

出于安全原因,Databricks 不鼓励向 GitHub 提供 Azure Databricks 工作区用户的个人访问令牌。 相反,Databricks 建议为 GitHub 提供与 Microsoft Entra ID 服务主体关联的 Microsoft Entra ID 令牌。 有关说明,请参阅 GitHub Actions 市场中运行 Databricks 笔记本 GitHub Actions 页的 Azure 部分。

重要

笔记本运行时拥有与令牌关联的标识的所有工作区权限,因此 Databricks 建议使用服务主体。 如果确实想要为 GitHub 提供 Azure Databricks 工作区用户的个人访问令牌以便仅进行个人探索,并且明白出于安全原因 Databricks 不鼓励这种做法,请参阅有关创建工作区用户的个人访问令牌的说明。

步骤 6.2:添加 GitHub Actions 工作流

在此子步骤中,你将添加 GitHub Actions 工作流以在存储库有拉取请求时运行 run_unit_tests 笔记本。

此子步骤将 GitHub Actions 工作流存储在一个文件中,该文件存储在 GitHub 存储库中的多个文件夹级别中。 GitHub Actions 需要存储库中存在特定的嵌套文件夹层次结构,才能正常工作。 若要完成此步骤,需要为 GitHub 存储库使用网站,因为 Azure Databricks Git 文件夹用户界面不支持创建嵌套文件夹层次结构。

  1. 在 GitHub 存储库的网站中,单击“代码”选项卡。

  2. 单击“主”旁边的箭头可展开“切换分支或标记”下拉列表

  3. 在“查找或创建分支”框中,输入 adding_github_actions

  4. 单击“创建分支: adding_github_actions from 'main'”。

  5. 单击“添加文件”>“创建新文件”。

  6. 对于“为文件命名”,请输入 .github/workflows/databricks_pull_request_tests.yml

  7. 在编辑器窗口中,输入以下代码。 此代码使用运行 Databricks Notebook GitHub Action 中的 pull_request 挂钩来运行 run_unit_tests 笔记本。

    在以下代码中,进行以下替换:

    • <your-workspace-instance-URL> 替换为 Azure Databricks 实例名称
    • <your-access-token> 替换为前面生成的令牌。
    • <your-cluster-id> 替换为目标群集 ID
    name: Run pre-merge Databricks tests
    
    on:
      pull_request:
    
    env:
      # Replace this value with your workspace instance name.
      DATABRICKS_HOST: https://<your-workspace-instance-name>
    
    jobs:
      unit-test-notebook:
        runs-on: ubuntu-latest
        timeout-minutes: 15
    
        steps:
          - name: Checkout repo
            uses: actions/checkout@v2
          - name: Run test notebook
            uses: databricks/run-notebook@main
            with:
              databricks-token: <your-access-token>
    
              local-notebook-path: notebooks/run_unit_tests.py
    
              existing-cluster-id: <your-cluster-id>
    
              git-commit: "${{ github.event.pull_request.head.sha }}"
    
              # Grant all users view permission on the notebook's results, so that they can
              # see the result of the notebook, if they have related access permissions.
              access-control-list-json: >
                [
                  {
                    "group_name": "users",
                    "permission_level": "CAN_VIEW"
                  }
                ]
              run-name: "EDA transforms helper module unit tests"
    
  8. 单击“提交更改”。

  9. 在“提交更改”对话框中,将 Create databricks_pull_request_tests.yml 输入“提交消息”

  10. 选择“直接提交到 adding_github_actions 分支”,然后单击“提交更改”

  11. 在“代码”选项卡上,单击“比较并拉取请求”,然后创建拉取请求。

  12. 在拉取请求页上,等待“运行预合并 Databricks 测试 / unit-test-notebook (pull_request)”旁边的图标显示绿色复选标记。 (图标可能需要一些时间才能显示。)如果出现红色 X 而不是绿色复选标记,请单击“详细信息”以找出原因。 如果图标或“详细信息”不再显示,请单击“显示所有检查”。

  13. 如果出现绿色复选标记,请将拉取请求合并到 main 分支。

(可选)步骤 7:更新 GitHub 中的共享代码以触发测试

此步骤中,将对共享代码进行更改,然后将更改推送到 GitHub 存储库,这会根据上一步中的 GitHub Actions 立即自动触发测试。

步骤 7.1:在存储库中创建其他工作分支

  1. 在“工作区”浏览器中,打开“best-notebooks”Git 文件夹
  2. 在文件夹名称旁边,单击“first_tests”Git 分支按钮。
  3. 在“best-notebooks”对话框中,单击“first_tests”分支旁的下拉箭头,然后选择“主要”
  4. 单击“拉取”按钮。 如果系统提示继续拉取,请单击“确认”。
  5. 单击 +(创建分支)按钮。
  6. 输入 trigger_tests,然后单击“创建”。 (可为分支提供其他名称。)
  7. 关闭此对话框。

步骤 7.2:更改共享代码

  1. 在“工作区”浏览器的“best-notebooks”Git 文件夹中,单击“covid_analysis/transforms.py”文件

  2. 更改此文件的第三行:

    # Filter by country code.
    

    更改为:

    # Filter by country code. If not specified, use "USA."
    

步骤 7.3:签入更改以触发测试

  1. 在文件名称旁边,单击“trigger_tests”Git 分支按钮。
  2. 在 best-notebooks 对话框中的“更改”选项卡上,确保已选中 covid_analysis/transforms.py。
  3. 对于“提交消息(必填)”,请输入 Updated comment
  4. 对于“说明”(可选),请输入 This updates the comment for filter_country.
  5. 单击“提交和推送”。
  6. 单击横幅中“在 git 提供程序上创建拉取请求”中的拉取请求链接,然后在 GitHub 中创建拉取请求
  7. 在拉取请求页上,等待“运行预合并 Databricks 测试 / unit-test-notebook (pull_request)”旁边的图标显示绿色复选标记。 (图标可能需要一些时间才能显示。)如果出现红色 X 而不是绿色复选标记,请单击“详细信息”以找出原因。 如果图标或“详细信息”不再显示,请单击“显示所有检查”。
  8. 如果出现绿色复选标记,请将拉取请求合并到 main 分支。