開始
加載和管理數據
處理數據
政府
引用和資源
2023年4月27日更新
給我們反饋
請注意
本文涵蓋了詹金斯,既不提供也不支持數據磚。聯係供應商,看詹金斯幫助。
持續集成和持續交付(CI / CD)是指開發和交付軟件的過程簡而言之,通過使用自動化管道頻繁的周期。這決不是一個新進程,無處不在的幾十年來在傳統的軟件工程,它正成為一個越來越必要的過程工程和數據科學團隊。為了使數據產品是有價值的,他們必須及時交付。此外,消費者必須有信心在這些產品結果的有效性。通過自動化的構建、測試和部署代碼,開發團隊能夠提供更頻繁地發布和可靠地比手工流程仍普遍在許多工程和數據科學團隊。
持續集成始於實踐您提交您的代碼的一些頻率源代碼存儲庫中的一個分支。然後每個提交合並與其他開發人員的承諾,以確保沒有衝突。變化是進一步驗證通過創建一個構建和運行自動化測試與構建。這個過程最終導致工件,或部署包,最終將部署到目標環境中,在這種情況下一個磚的工作區。
雖然可以根據您的需要,不同的典型配置數據磚管道包括以下步驟:
持續集成:
代碼
開發代碼和單元測試磚筆記本或使用一個外部的IDE。
手動運行測試。
提交代碼和測試一個git分支。
構建
收集新的和更新的代碼和測試。
運行自動化測試。
構建Apache火花代碼庫和兒童。
發布:生成一個釋放工件。
持續交付:
部署
部署的筆記本。
配置庫。
測試:運行自動化測試並報告結果。
操作:通過編程工程進度數據,分析和機器學習的工作流。
第一個步驟在設計CI / CD決定代碼提交和管道的分支策略來管理新的和更新的代碼的開發和集成代碼目前在生產中沒有不良影響。這個決定需要選擇一個版本控製係統包含代碼和促進的促銷代碼。磚支持集成的GitHub, Bitbucket都,允許你提交筆記本git存儲庫。
如果你的版本控製係統不是那些支持通過直接筆記本集成,或者如果你想要更大的靈活性和控製比自助git集成,您可以使用磚CLI出口筆記本和提交本地機器。這個腳本應該運行在一個本地git存儲庫設置為與適當的遠程存儲庫同步。當執行時,這個腳本應該:
檢查所需的分支。
把新變化從遠程分支。
出口筆記本電腦使用磚CLI從磚工作區。
提示用戶提交消息或使用默認的如果一個人沒有提供。
提交更新後的筆記本到本地分支。
推動遠程分支的變化。
下麵的腳本執行以下步驟:
git checkout <分支> git拉磚工作區export_dir——概要文件<檔案> - o <路徑>。/工作區dt=”日期' + Y % - % - % d % H: % m: % S的”msg_default=“DB出口dt美元”讀- p“進入提交評論msg_default美元):“味精味精=$ {味精:-msg_default美元}回聲美元味精git添加。git commit - m“<提交消息>”git推
如果你喜歡在磚開發IDE而不是筆記本電腦,您可以使用內置的VCS集成特性現代IDE或git CLI提交代碼。
磚提供磚連接,一個SDK,連接ide磚集群。這是開發庫時特別有用,因為它允許您磚集群上運行代碼和單元測試,而無需部署代碼。看到磚連接限製確定是否支持你的用例。
磚現在建議你使用dbx由磚實驗室為當地的發展而不是磚連接。
根據您的分支策略和推廣過程中,點CI / CD管道將啟動建立會有所不同。然而,承諾從各種貢獻者的代碼最終將合並成一個指定的分支是構建和部署。分支管理步驟運行之外的磚,使用提供的版本控製係統的接口。
有許多CI / CD工具可以用來管理和執行你的管道。本文說明了如何使用詹金斯自動化服務器。CI / CD是一個設計模式,所以在這篇文章中概述的步驟和階段應該轉移一些更改管道在每個工具定義語言。此外,大部分的代碼在這個例子中管道運行標準的Python代碼,您可以調用其他工具。
詹金斯使用一個主服務協調和一個到多個執行代理。在本例中您使用默認永久代理節點包含在詹金斯服務器。您必須手動安裝以下工具和軟件包所需的代理上的管道,在這種情況下,詹金斯服務器:
Conda:一個開放源碼的Python環境管理體係。
Python 3.7:用於運行測試,構建一個部署輪,並執行部署腳本。Python的版本是很重要的,因為測試要求的Python版本運行在集群代理應該匹配的磚。這個示例使用磚7.3運行時,其中包括Python 3.7。
Python庫:請求,databricks-connect,databricks-cli,pytest。
請求
databricks-connect
databricks-cli
pytest
詹金斯提供了一些不同的項目類型創建CI / CD管道。這個例子實現了一個詹金斯管道。詹金斯管道提供一個接口來定義階段管道使用Groovy詹金斯代碼來調用和配置插件。
你寫一個管道定義在一個文本文件(稱為Jenkinsfile)進而檢查項目的版本控製存儲庫。有關更多信息,請參見詹金斯管道。下麵是一個示例管道:
/ / Jenkinsfile節點{defGITREPO=" / var / lib / jenkins /工作區/ $ {env.JOB_NAME} "defGITREPOREMOTE=“https://github.com/ <回購>”defGITHUBCREDID=“< github-token >”defCURRENTRELEASE=“<版本>”defDBTOKEN=“< databricks-token >”defDBURL=“https:// < databricks-instance >”defSCRIPTPATH=“$ {GITREPO} /自動化/部署”defNOTEBOOKPATH=“$ {GITREPO} /工作空間”defLIBRARYPATH=“$ {GITREPO} /庫”defBUILDPATH=" $ {GITREPO} /構建/ {env.JOB_NAME} - {env.BUILD_NUMBER}”美元defOUTFILEPATH=“$ {BUILDPATH} /驗證/輸出”defTESTRESULTPATH=" $ {BUILDPATH} /驗證/報告/ junit”defWORKSPACEPATH=“/共享/ <路徑>”defDBFSPATH=“dbfs: < dbfs-path >”defCLUSTERID=“< cluster-id >”defCONDAPATH=“< conda-path >”defCONDAENV=“< conda-env >”階段(“設置”){withCredentials([字符串(credentialsId:DBTOKEN,變量:“令牌”))){上海" " # ! / bin / bash#配置Conda部署和測試環境源$ {CONDAPATH} / bin / $ {CONDAENV}激活#為部署配置磚CLIecho " $ {DBURL}美元令牌”|磚配置——令牌#配置數據磚連接進行測試echo " $ {DBURL}美元的令牌$ {CLUSTERID}015001年“| databricks-connect配置”“”}}階段(“簽出”){/ /用於顯示目的回聲“把$ {CURRENTRELEASE}分支從Github”git分支機構:CURRENTRELEASE,credentialsId:GITHUBCREDID,url:GITREPOREMOTE}階段(“運行單元測試”){試一試{上海" " # ! / bin / bash#讓Conda環境測試源$ {CONDAPATH} / bin / $ {CONDAENV}激活# Python測試庫python3 - m pytest——junit-xml = $ {TESTRESULTPATH} / TEST-libout。xml $ {LIBRARYPATH} * / python / dbxdemo /測試。py | |真”“”}抓(犯錯){一步([美元的類:“JUnitResultArchiver”,檢測結果:”——junit-xml = $ {TESTRESULTPATH} /測試- * . xml”])如果(currentBuild。結果= =“不穩定”)currentBuild。結果=“失敗”扔犯錯}}階段(“包”){上海" " # ! / bin / bash#讓Conda環境測試源$ {CONDAPATH} / bin / $ {CONDAENV}激活#包Python庫cd $ {LIBRARYPATH} / python / dbxdemopython3設置。py sdist bdist_wheel”“”}階段(建立工件的){上海”““mkdir - p $ {BUILDPATH} /工作區mkdir - p $ {BUILDPATH} /圖書館/ pythonmkdir - p $ {BUILDPATH} /驗證/輸出#被修改的文件git diff——名義diff-filter AMR交頭接耳^ 1 = | xargs -“{}”cp -家長- r“{}”$ {BUILDPATH}#獲取打包填詞找到$ {LIBRARYPATH} - name”*。whl' | xargs -I '{}' cp '{}' ${BUILDPATH}/Libraries/python/#生成工件焦油-czvf構建/ latest_build.tar。廣州$ {BUILDPATH}”“”archiveArtifacts構件:“構建/ latest_build.tar.gz”}階段(“部署”){上海" " # ! / bin / bash#讓Conda環境測試源$ {CONDAPATH} / bin / $ {CONDAENV}激活#使用磚CLI部署的筆記本磚工作區import_dir $ {BUILDPATH} /工作區$ {WORKSPACEPATH}dbfs cp - r $ {BUILDPATH} /圖書館/ python $ {DBFSPATH}”“”withCredentials([字符串(credentialsId:DBTOKEN,變量:“令牌”))){上海" " # ! / bin / bash#得到圖書館的空間分隔的列表填詞= \ $(找到$ {BUILDPATH} /圖書館/ python / * - name”。whl年代# | sed。* / # #”|粘貼-標準差" ")#腳本卸載,重啟如果需要& instsall圖書館python3 $ {SCRIPTPATH} / installWhlLibrary。py——工作區= $ {DBURL} \——令牌= $令牌\——clusterid = $ {clusterid} \——libs = \ libs美元\——dbfspath = $ {dbfspath}”“”}}階段(“運行集成測試”){withCredentials([字符串(credentialsId:DBTOKEN,變量:“令牌”))){上海”““python3 $ {SCRIPTPATH} / executenotebook。py——工作區= $ {DBURL} \——令牌= $令牌\——clusterid = $ {clusterid} \——localpath = $ {NOTEBOOKPATH} \ /驗證——workspacepath = $ {workspacepath} \ /驗證——outfilepath = $ {outfilepath}”“”}上海" " " sed - i - e的# ENV # $ {OUTFILEPATH} g’$ {SCRIPTPATH} / evaluatenotebookruns.pypython3 - m pytest——junit-xml = $ {TESTRESULTPATH} / TEST-notebookout。xml $ {SCRIPTPATH} / evaluatenotebookruns。py | |真”“”}階段(“報告測試結果”){上海”““找到$ {OUTFILEPATH} - name”*。json' -exec gzip --verbose {} \\;觸摸$ {TESTRESULTPATH} /測試- * . xml”“”junit“* * /報告/ junit / * . xml”}}
本文的其餘部分討論了管道的每一步。
您可以定義環境變量允許管道階段中使用不同的管道。
作為一個安全最佳實踐,驗證自動化工具時,係統中,腳本和應用程序,磚屬於建議您使用訪問令牌服務主體而不是用戶工作區。為服務主體,創建訪問令牌管理服務主體的訪問令牌。
GITREPO:本地路徑git存儲庫根
GITREPO
GITREPOREMOTE:git存儲庫Web URL
GITREPOREMOTE
GITHUBCREDID:詹金斯憑據ID GitHub個人訪問令牌
GITHUBCREDID
CURRENTRELEASE:部署分支
CURRENTRELEASE
DBTOKEN:詹金斯憑據ID磚個人訪問令牌
DBTOKEN
DBURL:Web URL磚工作區
DBURL
SCRIPTPATH:本地路徑自動化腳本的git項目目錄
SCRIPTPATH
NOTEBOOKPATHgit項目目錄:本地路徑筆記本
NOTEBOOKPATH
LIBRARYPATHgit項目:本地路徑目錄庫代碼或其他DBFS代碼
LIBRARYPATH
BUILDPATH:本地路徑目錄構建工件
BUILDPATH
OUTFILEPATH:本地路徑從自動測試生成的JSON結果文件
OUTFILEPATH
TESTRESULTPATH:本地路徑目錄Junit測試結果總結
TESTRESULTPATH
WORKSPACEPATH筆記本電腦:磚工作區路徑
WORKSPACEPATH
DBFSPATH:磚DBFS路徑庫和兒童的代碼
DBFSPATH
CLUSTERID:磚集群ID來運行測試
CLUSTERID
CONDAPATH:Conda安裝路徑
CONDAPATH
CONDAENV:名字Conda環境包含構建依賴庫的
CONDAENV
在設置階段您配置數據磚CLI和磚與連接信息。
設置
defGITREPO=" / var / lib / jenkins /工作區/ $ {env.JOB_NAME} "defGITREPOREMOTE=“https://github.com/ <回購>”defGITHUBCREDID=“< github-token >”defCURRENTRELEASE=“<版本>”defDBTOKEN=“< databricks-token >”defDBURL=“https:// < databricks-instance >”defSCRIPTPATH=“$ {GITREPO} /自動化/部署”defNOTEBOOKPATH=“$ {GITREPO} /工作空間”defLIBRARYPATH=“$ {GITREPO} /庫”defBUILDPATH=" $ {GITREPO} /構建/ {env.JOB_NAME} - {env.BUILD_NUMBER}”美元defOUTFILEPATH=“$ {BUILDPATH} /驗證/輸出”defTESTRESULTPATH=" $ {BUILDPATH} /驗證/報告/ junit”defWORKSPACEPATH=“/共享/ <路徑>”defDBFSPATH=“dbfs: < dbfs-path >”defCLUSTERID=“< cluster-id >”defCONDAPATH=“< conda-path >”defCONDAENV=“< conda-env >”階段(“設置”){withCredentials([字符串(credentialsId:DBTOKEN,變量:“令牌”))){上海" " # ! / bin / bash#配置Conda部署和測試環境源$ {CONDAPATH} / bin / $ {CONDAENV}激活#為部署配置磚CLIecho " $ {DBURL}美元令牌”|磚配置——令牌#配置數據磚連接進行測試echo " $ {DBURL}美元的令牌$ {CLUSTERID}015001年“| databricks-connect配置”“”}}
的結帳階段從指定下載代碼分支代理執行代理使用一個詹金斯插件:
結帳
階段(“簽出”){/ /用於顯示目的回聲“把$ {CURRENTRELEASE}分支從Github”git分支機構:CURRENTRELEASE,credentialsId:GITHUBCREDID,url:GITREPOREMOTE}
有幾個不同的選項在決定如何單元測試代碼。為圖書館開發的代碼外磚筆記本,這個過程就像傳統的軟件開發實踐。你編寫一個單元測試使用的測試框架,像Pythonpytest模塊,和JUnit-formatted XML文件存儲測試結果。
磚過程不同,被測試的代碼是Apache引發火花集群上執行代碼的目的通常運行在本地或在這種情況下磚。為了滿足這種需求,你使用磚連接。自從SDK早些時候配置,不需要修改測試代碼磚集群上執行測試。你安裝了磚連接Conda虛擬環境中。一旦激活Conda環境,測試執行使用Python工具,pytest,你提供測試和由此產生的輸出文件的位置。
階段(“運行單元測試”){試一試{上海" " # ! / bin / bash#讓Conda環境測試源$ {CONDAPATH} / bin / $ {CONDAENV}激活# Python測試庫python3 - m pytest——junit-xml = $ {TESTRESULTPATH} / TEST-libout。xml $ {LIBRARYPATH} * / python / dbxdemo /測試。py | |真”“”}抓(犯錯){一步([美元的類:“JUnitResultArchiver”,檢測結果:”——junit-xml = $ {TESTRESULTPATH} /測試- * . xml”])如果(currentBuild。結果= =“不穩定”)currentBuild。結果=“失敗”扔犯錯}}
下麵的代碼片段是一個庫函數,可能是安裝在一個磚集群。這是一個簡單的函數,添加一個新列,由文字組成,一個Apache DataFrame火花。
# addcol.py進口pyspark.sql.functions作為Fdefwith_status(df):返回df。withColumn(“狀態”,F。點燃(“檢查”))
這個測試通過模擬DataFrame對象with_status中定義的函數,addcol.py。結果然後比較DataFrame對象包含預期的值。如果值匹配,在這種情況下,測試通過。
with_status
addcol.py
# test-addcol.py進口pytest從dbxdemo.spark進口get_spark從dbxdemo.appendcol進口with_status類TestAppendCol(對象):deftest_with_status(自我):source_data=((“波拉”,“白色”,“paula.white@example.com”),(“約翰。”,“貝爾”,“john.baer@example.com”)]source_df=get_spark()。createDataFrame(source_data,(“first_name”,“last_name”,“電子郵件”])actual_df=with_status(source_df)expected_data=((“波拉”,“白色”,“paula.white@example.com”,“檢查”),(“約翰。”,“貝爾”,“john.baer@example.com”,“檢查”)]expected_df=get_spark()。createDataFrame(expected_data,(“first_name”,“last_name”,“電子郵件”,“狀態”])斷言(expected_df。收集()= =actual_df。收集())
在包階段,你包庫代碼到一個Python輪。
包
階段(“包”){上海" " # ! / bin / bash#讓Conda環境測試源$ {CONDAPATH} / bin / $ {CONDAENV}激活#包Python庫cd $ {LIBRARYPATH} / python / dbxdemopython3設置。py sdist bdist_wheel”“”}
建立一個部署構件磚包括收集所有新的或更新的代碼部署到適當的磚的環境。在構建工件階段添加筆記本代碼部署到工作區,whl構建過程生成的庫,以及測試結果總結,用於存檔。要做到這一點,你使用gitdiff標記所有新文件已經包含在最新git合並。這隻是一個例子的方法,實現在你的管道可能有所不同,但目標是將所有文件用於當前版本。
構建工件
whl
gitdiff
階段(建立工件的){上海”““mkdir - p $ {BUILDPATH} /工作區mkdir - p $ {BUILDPATH} /圖書館/ pythonmkdir - p $ {BUILDPATH} /驗證/輸出#被修改的文件git diff——名義diff-filter AMR交頭接耳^ 1 = | xargs -“{}”cp -家長- r“{}”$ {BUILDPATH}#獲取打包填詞找到$ {LIBRARYPATH} - name”*。whl' | xargs -I '{}' cp '{}' ${BUILDPATH}/Libraries/python/#生成工件焦油-czvf構建/ latest_build.tar。廣州$ {BUILDPATH}”“”archiveArtifacts構件:“構建/ latest_build.tar.gz”}
在部署階段使用磚CLI,就像早些時候使用的磚連接模塊,安裝在你Conda環境,所以你必須為這個shell會話激活它。你使用工作區CLI和DBFS CLI上傳筆記本和庫,分別為:
磚工作區import_dir <當地的構建路徑> <遠程工作區路徑> dbfs cp - r <當地的構建路徑> <遠程dbfs路徑>
階段(“部署”){上海" " # ! / bin / bash#讓Conda環境測試源$ {CONDAPATH} / bin / $ {CONDAENV}激活#使用磚CLI部署的筆記本磚工作區import_dir $ {BUILDPATH} /工作區$ {WORKSPACEPATH}dbfs cp - r $ {BUILDPATH} /圖書館/ python $ {DBFSPATH}”“”withCredentials([字符串(credentialsId:DBTOKEN,變量:“令牌”))){上海" " # ! / bin / bash#得到圖書館的空間分隔的列表填詞= \ $(找到$ {BUILDPATH} /圖書館/ python / * - name”。whl年代# | sed。* / # #”|粘貼-標準差" ")#腳本卸載,重啟如果需要& instsall圖書館python3 $ {SCRIPTPATH} / installWhlLibrary。py——工作區= $ {DBURL} \——令牌= $令牌\——clusterid = $ {clusterid} \——libs = \ libs美元\——dbfspath = $ {dbfspath}”“”}}
安裝新版本庫的磚集群要求您首先卸載現有的圖書館。要做到這一點,你調用磚REST API在一個Python腳本執行以下步驟:
檢查是否安裝了圖書館。
卸載圖書館。
重新啟動集群是否進行卸載。
等到再次集群運行之前。
安裝該庫。
# installWhlLibrary.py# ! / usr / bin / python3進口json進口請求進口sys進口getopt進口時間def主要():工作空間=”令牌=”clusterid=”填詞=”dbfspath=”試一試:選擇,arg遊戲=getopt。getopt(sys。argv(1:,“hstcld”,(“工作區= ',“令牌= ',“clusterid = ',“填詞=”,“dbfspath = '])除了getopt。GetoptError:打印(“installWhlLibrary。py -s -t -c -l -d ')sys。退出(2)為選擇,參數在選擇:如果選擇= =“- h”:打印(“installWhlLibrary。py -s -t -c -l -d ')sys。退出()elif選擇在(“s”,“——工作區”):工作空間=參數elif選擇在(“t”,“——令牌”):令牌=參數elif選擇在(“c”,“——clusterid”):clusterid=參數elif選擇在(“- l”,“那——libs”):填詞=參數elif選擇在(“- d”,“——dbfspath”):dbfspath=參數打印(“s”+工作空間)打印(“- t是”+令牌)打印(“c”+clusterid)打印(“- l是”+填詞)打印(“- d”+dbfspath)libslist=填詞。分裂()#卸載圖書館如果存在於集群我=0為自由在libslist:dbfslib=dbfspath+自由打印(dbfslib+“:”+getLibStatus(工作空間,令牌,clusterid,dbfslib))如果(getLibStatus(工作空間,令牌,clusterid,dbfslib)! =“沒有找到”):打印(dbfslib+”存在。卸載。”)我=我+1值={“cluster_id”:clusterid,“庫”:[{“whl”:dbfslib}]}分別地=請求。帖子(工作空間+/ api / 2.0 /圖書館/卸載的,數據=json。轉儲(值),身份驗證=(“令牌”,令牌))runjson=分別地。文本d=json。加載(runjson)打印(dbfslib+”後,“+getLibStatus(工作空間,令牌,clusterid,dbfslib))#如果庫卸載重啟如果我>0:值={“cluster_id”:clusterid}打印(重新啟動集群:“+clusterid)分別地=請求。帖子(工作空間+“/ api / 2.0 /集群/重啟”,數據=json。轉儲(值),身份驗證=(“令牌”,令牌))restartjson=分別地。文本打印(restartjson)p=0等待=真正的而等待:時間。睡眠(30.)clusterresp=請求。得到(工作空間+' / api / 2.0 /集群/ ? cluster_id = '+clusterid,身份驗證=(“令牌”,令牌))clusterjson=clusterresp。文本jsonout=json。加載(clusterjson)current_state=jsonout(“狀態”]打印(clusterid+”狀態:“+current_state)如果current_state在(“奔跑”,“INTERNAL_ERROR”,“跳過”]或p> =10:打破p=p+1#安裝庫為自由在libslist:dbfslib=dbfspath+自由打印(“安裝”+dbfslib)值={“cluster_id”:clusterid,“庫”:[{“whl”:dbfslib}]}分別地=請求。帖子(工作空間+/ api / 2.0 /圖書館/安裝的,數據=json。轉儲(值),身份驗證=(“令牌”,令牌))runjson=分別地。文本d=json。加載(runjson)打印(dbfslib+”後,“+getLibStatus(工作空間,令牌,clusterid,dbfslib))defgetLibStatus(工作空間,令牌,clusterid,dbfslib):分別地=請求。得到(工作空間+' / api / 2.0 /圖書館/集群狀態? cluster_id = '+clusterid,身份驗證=(“令牌”,令牌))libjson=分別地。文本d=json。加載(libjson)如果(d。得到(“library_statuses”)):狀態=d(“library_statuses”]為狀態在狀態:如果(狀態(“圖書館”]。得到(“whl”)):如果(狀態(“圖書館”][“whl”]= =dbfslib):返回狀態(“狀態”]其他的:返回“沒有找到”其他的:#沒有發現庫返回“沒有找到”如果__name__= =“__main__ ':主要()
一旦工件被部署,重要的是要運行集成測試,以確保所有的代碼一起工作在新的環境。要做到這一點,你可以運行一個筆記本包含斷言測試部署。在這種情況下,您正在使用相同的測試中使用單元測試,但現在是進口安裝appendcol圖書館的whl這隻是在集群上安裝。
appendcol
自動化測試,包括你的CI / CD管道,使用磚REST API的筆記本從詹金斯服務器運行。這允許您檢查筆記本運行是否通過或失敗pytest。如果筆記本的斷言失敗,這將是由REST API返回的JSON輸出所示,隨後在JUnit測試結果。
階段(“運行集成測試”){withCredentials([字符串(credentialsId:DBTOKEN,變量:“令牌”))){上海”““python3 $ {SCRIPTPATH} / executenotebook。py——工作區= $ {DBURL} \——令牌= $令牌\——clusterid = $ {clusterid} \——localpath = $ {NOTEBOOKPATH} \ /驗證——workspacepath = $ {workspacepath} \ /驗證——outfilepath = $ {outfilepath}”“”}上海" " " sed - i - e的# ENV # $ {OUTFILEPATH} g’$ {SCRIPTPATH} / evaluatenotebookruns.pypython3 - m pytest——junit-xml = $ {TESTRESULTPATH} / TEST-notebookout。xml $ {SCRIPTPATH} / evaluatenotebookruns。py | |真”“”}
這個階段調用兩個Python自動化腳本。第一個腳本,executenotebook.py,筆記本使用創建並觸發一次運行(帖子/ /運行/提交工作)端點提交一個匿名的工作。因為這個端點是異步的,它使用REST調用返回的任務ID最初調查工作的狀態。一旦工作完成,JSON輸出保存到指定的路徑在調用函數參數傳遞。
executenotebook.py
帖子/ /運行/提交工作
# executenotebook.py# ! / usr / bin / python3進口json進口請求進口操作係統進口sys進口getopt進口時間def主要():工作空間=”令牌=”clusterid=”localpath=”workspacepath=”outfilepath=”試一試:選擇,arg遊戲=getopt。getopt(sys。argv(1:,“海關:t: c:靠”,(“工作區= ',“令牌= ',“clusterid = ',“localpath = ',“workspacepath = ',“outfilepath = '])除了getopt。GetoptError:打印(“executenotebook。py -s -t -c -l -w -o )')sys。退出(2)為選擇,參數在選擇:如果選擇= =“- h”:打印(“executenotebook。py -s -t -c -l -w -o ')sys。退出()elif選擇在(“s”,“——工作區”):工作空間=參數elif選擇在(“t”,“——令牌”):令牌=參數elif選擇在(“c”,“——clusterid”):clusterid=參數elif選擇在(“- l”,“——localpath”):localpath=參數elif選擇在(“- w”,“——workspacepath”):workspacepath=參數elif選擇在(“o”,“——outfilepath”):outfilepath=參數打印(“s”+工作空間)打印(“- t是”+令牌)打印(“c”+clusterid)打印(“- l是”+localpath)打印(“- w是”+workspacepath)打印(“- o '+outfilepath)#從走本地路徑生成數組筆記本電腦=[]為路徑,子目錄,文件在操作係統。走(localpath):為的名字在文件:fullpath=路徑+' / '+的名字#刪除localpath回購,但保持工作區路徑fullworkspacepath=workspacepath+路徑。取代(localpath,”)的名字,file_extension=操作係統。路徑。splitext(fullpath)如果file_extension。較低的()在(. scala的,. sql的,“r”,. py的]:行=(fullpath,fullworkspacepath,1]筆記本電腦。附加(行)#運行每個元素列表為筆記本在筆記本電腦:nameonly=操作係統。路徑。basename(筆記本(0])workspacepath=筆記本(1]的名字,file_extension=操作係統。路徑。splitext(nameonly)# workpath刪除擴展fullworkspacepath=workspacepath+' / '+的名字打印(的工作:+fullworkspacepath)值={“run_name”:的名字,“existing_cluster_id”:clusterid,“timeout_seconds”:3600年,“notebook_task”:{“notebook_path”:fullworkspacepath}}分別地=請求。帖子(工作空間+' / api / 2.0 /工作/運行/提交的,數據=json。轉儲(值),身份驗證=(“令牌”,令牌))runjson=分別地。文本打印(”runjson:“+runjson)d=json。加載(runjson)runid=d(“run_id”]我=0等待=真正的而等待:時間。睡眠(10)jobresp=請求。得到(工作空間+' / api / 2.0 /工作/運行/ ? run_id = '+str(runid),數據=json。轉儲(值),身份驗證=(“令牌”,令牌))jobjson=jobresp。文本打印(”jobjson:“+jobjson)j=json。加載(jobjson)current_state=j(“狀態”][“life_cycle_state”]runid=j(“run_id”]如果current_state在(“終止”,“INTERNAL_ERROR”,“跳過”]或我> =12:打破我=我+1如果outfilepath! =”:文件=開放(outfilepath+' / '+str(runid)+. json的,' w ')文件。寫(json。轉儲(j))文件。關閉()如果__name__= =“__main__ ':主要()
第二個腳本,evaluatenotebookruns.py,定義了test_job_run函數,解析和評價JSON來確定在筆記本通過還是失敗的斷言語句。一個額外的測試,test_performance,捕獲測試運行比預期更長的時間。
evaluatenotebookruns.py
test_job_run
test_performance
# evaluatenotebookruns.py進口unittest進口json進口一團進口操作係統類TestJobOutput(unittest。TestCase):test_output_path=“# ENV #”deftest_performance(自我):路徑=自我。test_output_path狀態=[]為文件名在一團。一團(操作係統。路徑。加入(路徑,‘* . json‘)):打印(的評價:“+文件名)數據=json。負載(開放(文件名))持續時間=數據(“execution_duration”]如果持續時間>100000年:狀態=“失敗”其他的:狀態=“成功”狀態。附加(狀態)自我。assertFalse(“失敗”在狀態)deftest_job_run(自我):路徑=自我。test_output_path狀態=[]為文件名在一團。一團(操作係統。路徑。加入(路徑,‘* . json‘)):打印(的評價:“+文件名)數據=json。負載(開放(文件名))狀態=數據(“狀態”][“result_state”]狀態。附加(狀態)自我。assertFalse(“失敗”在狀態)如果__name__= =“__main__ ':unittest。主要()
你見過在單元測試階段,使用pytest運行測試並生成結果摘要。
JSON結果存檔和詹金斯使用發布測試結果junit詹金斯插件。這使您能夠可視化報告和儀表板與構建過程的狀態有關。
junit
階段(“報告測試結果”){上海”““找到$ {OUTFILEPATH} - name”*。json' -exec gzip --verbose {} \\;觸摸$ {TESTRESULTPATH} /測試- * . xml”“”junit“* * /報告/ junit / * . xml”}
此時,CI / CD管道已完成集成和部署周期。通過自動化這個過程,你可以確保你的代碼測試和部署了一個高效的、一致的、可重複的過程。