資料庫與Redgate SQL Toolbelt和Azure DevOps的持續整合

Tybyq發表於2018-12-10

理論與實踐中的資料庫CI

CI背後的理論是,如果我們每天多次將程式碼整合到共享儲存庫中,然後透過執行自動構建和後續測試來驗證每個提交,那麼我們會及早發現並根除問題,並提高軟體的質量。

本文的內容是關於設定管道,使您能夠將CI理論付諸實踐,用於資料庫。當我在2013年釋出關於這個主題的原始文章時,它使用了SVN和Jenkins,並且證明非常受歡迎。這仍然是一條可行的路線,但在我們的行業中,半年是永恆的,其他技術和工具也越來越受歡迎。PowerShell已經成為Microsoft堆疊的主要指令碼語言,而Git是每個人都流行的原始碼控制工具。Jenkins,或者甚至是TeamCity,仍然可以輕鬆地用於CI伺服器,但上個月Azure DevOps取代了Visual Studio Team Services(VSTS),感覺它是撰寫2013年原始帖子新版本的最佳時機。Azure DevOps有免費套餐 任何想要學習本教程的人都可以使用。

因此,本文將使用:

  • Git  - 作為源控制系統。

  • Azure DevOps  - 託管遠端Git倉庫並自動化資料庫構建

  • Redgate SQL原始碼控制(SoC)  - 在本地提交資料庫更改。我們克隆遠端倉庫然後將其連結到SoC,因此我們可以直接從SSMS提交資料庫更改

  • PowerShell  - 將提交推送到Azure DevOps上託管的遠端儲存庫

  • Redgate SQL Change Automation(SCA)  - 使用PowerShell cmdlet自動執行本地資料庫構建(可選步驟)

  • Azure DevOps的SCA外掛  - 自動化資料庫構建和部署過程

當然,僅僅因為你現在擁有一些CI工具就說你是CI實踐者,就像你購買第一架望遠鏡時聲稱自己是天文學家一樣。這些工具只是必要的第一步。團隊仍然需要採用良好的CI實踐。開發人員需要編寫單元測試,證明每個小的更改都有效。他們必須儘可能多地每天多次提交對共享原始碼控制儲存庫的更改。每次提交都應觸發自動資料庫構建,以確保團隊始終具有可用的資料庫構建過程。每天晚上,團隊應該執行整合測試(本文未涉及),以證明所有單獨的單元一起工作以實現所需的過程。這些CI實踐自然會導致自動部署,

當然,你可以在沒有這些工具的情況下練習CI,但是工具越好,你就能找到更容易和更有價值的CI,就像望遠鏡和天文學一樣。

你需要什麼來開始

本文假定您對SQL Server,Git和PowerShell有基本的瞭解。為了重現這個概念證明,我使用了以下軟體版本:

  • 具有管理員訪問許可權的 Windows Server 2016 VM 。您還應該能夠在Windows 10上使用所有類似的結果。

  • SQL Server 2017開發人員版 。你可以在這裡下載。

  • Redgate SQL Toolbelt(2018年10月版) 。您可以在這裡下載它,它提供14天免費試用。特別是,您需要在本地工作站上安裝 SQL Source Control SQL Change Automation

  • Git 2.19 。你可以在這裡下載。

  • Azure DevOps帳戶 ,您可以在這裡免費建立一個 帳戶

您可以使用該軟體的較舊版本或較新版本,但由於Azure DevOps是託管服務,而且時間是一個複雜的問題,我不會對相容性做出任何承諾。同樣,如果您將來幾個月或幾年閱讀此帖子,您可能會發現Azure DevOps UI已更改:

您還需要一個資料庫來玩。我將使用StackOverflow資料庫,因為它有一個簡單的架構,我知道它的工作原理。對於您的第一次構建,嘗試使用可以單獨構建的簡單內容 localDB 。這不包括 AdventureWorks ,因為 localDB 不支援全文搜尋。此外,現在嘗試避免依賴於其他資料庫的資料庫。

步驟1:建立新的Azure DevOps專案並克隆儲存庫

導航到Azure DevOps中的 Projects 選項卡(在我的例子中,https://dev.azure.com/DLMConsultants/_projects)

資料庫與Redgate SQL Toolbelt和Azure DevOps的持續整合

為專案指定名稱 ,例如資料庫的名稱。在 版本控制下, 選擇 Git ,然後選擇您的首選 工作項 流程。如果有疑問,預設的工作項流程(敏捷)很好,因為它對本教程沒有任何影響。

資料庫與Redgate SQL Toolbelt和Azure DevOps的持續整合

將repo克隆到本地工作站 。要執行此操作,請複製Azure DevOps中的HTTPS連結:

資料庫與Redgate SQL Toolbelt和Azure DevOps的持續整合

現在,開啟PowerShell視窗,導航到您要儲存原始碼的目錄並克隆repo。基本命令如下所示:

git  clone  https://yourcompany@dev.azure.com/etc

這是我的完整命令視窗:
資料庫與Redgate SQL Toolbelt和Azure DevOps的持續整合

您現在應該在計算機上有一個本地儲存庫,其中包含一個隱藏的 .git 目錄,您可以在其中新增資料庫原始碼。

資料庫與Redgate SQL Toolbelt和Azure DevOps的持續整合

第2步:將資料庫連結到源

我們將使用Redgate SQL Source Control,因此請確保已安裝並且您可以在SSMS中訪問您的資料庫。開啟SSMS並右鍵單擊要連結到原始碼管理的開發或測試資料庫。選擇“將 資料庫連結到原始碼管理...  ”

資料庫與Redgate SQL Toolbelt和Azure DevOps的持續整合

Redgate SQL Source Control將在查詢視窗中開啟。選擇“  連結到我的原始碼管理系統  ”,從支援的原始碼管理系統中選擇“  Git  ”,然後貼上到本地原始碼控制儲存庫的路徑中。然後單擊“  瀏覽  ”和“建立 新資料夾  ”並將“  狀態  ”目錄新增到源控制元件儲存庫的根目錄,並將資料庫連結到狀態目錄。其原因將在步驟2.1中變得清晰。

資料庫與Redgate SQL Toolbelt和Azure DevOps的持續整合

成功連結後,請注意 RedGate.ssc 檔案已新增到Git  倉庫 中的“  state  ”目錄中。然後轉到Redgate SQL Source Control中的“  Commit  ”選項卡,您將看到所有資料庫物件的列表,準備提交給原始碼管理。確保選中所有物件,鍵入提交訊息並單擊 commit

資料庫與Redgate SQL Toolbelt和Azure DevOps的持續整合

當SQL Source Control表示所有更改都已提交時,請再次檢視您的git倉庫。您應該看到所有資料庫物件都編寫到各種目錄中。

資料庫與Redgate SQL Toolbelt和Azure DevOps的持續整合

由於Git是一個分散式原始碼控制系統,因此您只需將這些更改提交到本地倉庫。您尚未將這些檔案推送到Azure DevOps中託管的遠端倉庫。為此,請再次開啟PowerShell終端,導航到git repo的根目錄並執行命令: git push。

資料庫與Redgate SQL Toolbelt和Azure DevOps的持續整合

您可能會在SQL原始碼管理提交選項卡中看到“  推送  ”按鈕,但它可能無法正常工作。這是Azure DevOps中託管的Redgate SQL Source Control和Git repos的已知問題。雖然有點令人沮喪,但開啟PowerShell終端並輸入“git push”並不是很麻煩,而且SQL Toolbelt中的其他功能可以彌補它。也就是說,如果破碎的“推送”按鈕讓你煩惱,你可以在這裡新增你的投票。

將原始碼推送到Azure DevOps之後,您應該能夠在Azure DevOps網站的“  程式碼  ”選項卡下看到它:

資料庫與Redgate SQL Toolbelt和Azure DevOps的持續整合

步驟2.1:使用SCA和PowerShell編寫資料庫構建指令碼(可選步驟)

我們現在在原始碼控制中有我們的資料庫,所以下一步是設定一個構建過程來檢查我們的原始碼是否“編譯”。透過這個,我的意思是它是可部署的。例如,如果原始檔中存在一些非法的T-SQL語法,'或者如果某些檢視缺少依賴項,可能是因為我重構了一些表,但忘記更新我的檢視,那麼SQL Server將無法執行我的原始碼,我的資料庫構建將失敗。

此步驟是可選的,或者至少使用PowerShell在本地執行它是可選的。另一種方法是“跳過此步驟直接跳到步驟3,開始在Azure DevOps上配置資料庫構建。但是,我喜歡先在本地執行我的構建。它幫助我瞭解幕後發生的事情。它還幫助我瞭解我的第一個構建是否由於我的原始碼或我的Azure DevOps配置而失敗。

在原始碼管理的根目錄中 在“  state  ”目錄旁邊建立一個名為“  build  ” 的新目錄。這解釋了為什麼我沒有在步驟2中將我的資料庫連結到我的Git倉庫的根目錄。將其他相關檔案放在原始碼管理中是有用的,但是你不想將它們放在你的Redgate資料夾中。

資料庫與Redgate SQL Toolbelt和Azure DevOps的持續整合

使用localdb驗證構建

在構建目錄中建立一個名為“  build.ps1  ” 的新檔案,並將以下PowerShell程式碼複製到其中。您可能希望更改引數的預設值 $packageID 以反映資料庫的名稱。現在,您應該保留其他引數。我將很快解釋 $packageVersion,$packagePath $testPath 引數,我將在進一步擴充套件下解釋其他。

PARAM
      [ string ] $ packageVersion  =  '0.1' ,
      [ string ] $ packageID  =  'StackOverflow' ,
      [ string ] $ packagePath  =  'C:\ packages' ,
      [ string ] $  testPath =  'C:\ testResults' ,
      [ string ] $ targetServerInstance  =  'TARGETSERVERINSTANCE' ,
      [ string ] $ targetDatabase   =  'TARGETDATABASE'

$ errorActionPreference  =  “停止”

匯入模組 SqlChangeAutomation  - ErrorAction  silentlycontinue  - ErrorVariable  + ImportErrors

“*****引數*****
packageVersion  是 $ packageVersion
packageID  是 $ packageID
packagePath  是 $ packagePath
testPath  是 $ testPath
* * * * * * * * * * * * * * * * * * * * * * “|寫入輸出

#在父目錄中搜尋狀態資料夾
$ myDir  =  Split-Path  - Parent  $ MyInvocation 。我的命令。路徑
$ scriptsFolder  =  Join-Path  - Path  $ myDir  - ChildPath  '.. \ state'
$ scriptsFolder
如果 (-not  (測試的路徑 - PathType  集裝箱 $ scriptsFolder ))
{
      寫錯誤 “ 無法找到$ scriptsFolder ”
}

#Using Redgate SCA驗證狀態目錄中的程式碼
嘗試
{
      $ validatedScriptsFolder  =  Invoke-DatabaseBuild  $ scriptsFolder   #-SQLCompareOptions'NoTransactions'
}
趕上 #
{
      $ _ 。例外。資訊
      “ $($資料庫。名稱; )無法驗證,因為$($ _ 。異常。訊息)”  |  Foreach {
            寫錯誤 $ _
      }
}
<#
#匯出NuGet包
 $ databasePackage = New-DatabaseBuildArtifact $ validatedScriptsFolder -PackageId $ packageID -PackageVersion $ packageVersion
 Export-DatabaseBuildArtifact $ databasePackage -Path $ packagePath
#執行測試
 $ testResultsFile =“$ testPath \ $ packageID.junit。$ packageVersion.xml”
 $ results = Invoke-DatabaseTests $ databasePackage
 Export-DatabaseTestResults $ results -OutputFile $ testResultsFile
#同步測試資料庫
 $ targetDB = New-DatabaseConnection -ServerInstance $ targetServerInstance -Database $ targetDatabase
 Test-DatabaseConnection $ targetDB
 Sync-DatabaseSchema -Source $ databasePackage -Target $ targetDB
 #>

此PowerShell程式碼使用SQL Change Automation在其中建立新資料庫 localDB 並將所有原始碼部署到該資料庫。一旦部署了資料庫,SQL Change Automation就會立即將其刪除,因為它已經達到了目的。如果您每週執行10次構建一週,則不希望有50個測試資料庫。

您應該能夠從PowerShell執行指令碼,如果您願意,可以覆蓋預設引數。

CD  的 根目錄 中 的 源 控制\ 構建
。\ build 。ps1  - packageVersion'0.1  '  - packageID'MyDatabase  '

這是完整的命令視窗,來自我的例子:

資料庫與Redgate SQL Toolbelt和Azure DevOps的持續整合

如果您的構建指令碼有效,那太好了!如果沒有,你可能會發現一些破碎的程式碼,也很棒!通常,這些是程式碼損壞,缺少依賴性, localDB 未安裝或SQL Server憑據不正確的結果。PowerShell輸出是你的朋友。

使用臨時資料庫驗證構建

您可能會遇到無法部署資料庫的情況 localDB ,例如,它缺少對某些其他資料庫的依賴關係,或者使用 localDB 不支援的SQL Server功能。例如, AdventureWorks 使用不會部署到的全文搜尋 localDB 。相反,您可以在“temproary”SQL Serve例項上部署到資料庫,該例項設定了資料庫所需的所有功能,依賴項,檔案組等。(請參閱Invoke-DatabaseBuild cmdlet文件中的示例3和4。)

您可以下載一個PowerShell構建指令碼(DBBuildTempServer.ps1),以稍微不同的樣式編寫,以展示可能的方法,以瞭解它是如何工作的。
您應該能夠從PowerShell執行指令碼,如果您願意,可以覆蓋預設引數。

CD  的 根目錄 中 的 源 控制\ 構建
。\ build 。ps1  - packageVersion'0.1   '  - packageID'MyDatabase   '   - TempServer'MyServerInstance  '  - User_id   ''  - 密碼 ''

如果您沒有可用於此過程的SQL Server例項,只需 -TemporaryDatabaseServer $TempconnectionString 從SCA  Invoke-DatabaseBuild 命令中刪除它,它將使用 localDB ,如前所述。Phil Factor的文章還提供了許多有關使用PowerShell和SCA的額外資訊。

建立NuGet包

在這個階段,我們所做的就是驗證構建; 換句話說,證明了資料庫將成功構建。完成後,我們可以開始探索其他SCA cmdlet,它們將從經過驗證的構建生成並匯出資料庫構建工件,在其上執行我們的測試套件,然後部署測試的更改,以使目標資料庫與經過驗證和測試的同步資源。

我將在稍後的“ 擴充套件”部分中介紹測試和同步cmdlet ,但是現在您可能希望生成一個NuGet包。NuGet包可以用作構建工件,代表了基於包的部署和持續交付的重要里程碑。您只需在構建指令碼中取消註釋幾行程式碼即可生成NuGet包。

只需在底部註釋塊中的#Export NuGet包下立即取消註釋兩行(例如,將<#幾行移動到下面),並確保預設值為 $packagePath 不在git倉庫中的現有目錄。如果你把它留空,它將在你的git repo的build目錄中建立一個NuGet包,我不推薦。

現在,當您執行成功的構建時,將建立包含原始碼的NuGet包。請注意,如果您嘗試建立兩個具有相同 $packageID $packageVersion 相同 $packagePath 的包,則構建將失敗,因此您需要覆蓋構建號或每次重新執行構建時刪除舊包。

提交對原始碼管理的更改並將其推送到伺服器。

> git  add  build。PS1
> git  commit  - m  “新增構建指令碼”
> git  推

資料庫與Redgate SQL Toolbelt和Azure DevOps的持續整合

第3步:使用Azure DevOps自動構建

您現在擁有原始碼管理中的資料庫程式碼,並將其推送到Azure DevOps。如果您按照步驟2.1中的說明進行操作,那麼您還可以在原始碼管理中使用PowerShell指令碼來構建資料庫,並且您知道原始碼是“編譯”的。現在,我們希望每次將新更改推送到原始碼控制時,Azure DevOps都會構建資料庫,以驗證是否可以部署更改並捕獲任何錯誤。

我們將使用Redgate Azure DevOps擴充套件來自動化資料庫構建,因為這不需要您遵循步驟2.1。如果您確實按照步驟2.1而不是使用Redgate外掛,則可能更喜歡使用執行build.ps1檔案的原始PowerShell任務來執行構建指令碼,並根據需要覆蓋預設引數。如果採用該方法,您可能會發現Azure DevOps預定義變數的索引很有用,您可能希望使用$(Build.BuildNumber)或$(Build.BuildID)來建立具有順序版本號的包。

您的自動構建將由“構建代理”執行。如果您已經 localDB 可以單獨構建資料庫,則應該能夠立即使用託管構建代理。否則,您需要在託管的伺服器上配置本地代理,該伺服器可以訪問合適的目標SQL Server例項以執行構建。

在Azure DevOps中,將滑鼠懸停在“  管道” 選項卡上,然後從下拉選單中選擇“  構建  ”。

資料庫與Redgate SQL Toolbelt和Azure DevOps的持續整合

點選 New Pipeline 按鈕,確保選擇了正確的源控制儲存庫和主分支。然後為模板選擇“  空作業  ”。

資料庫與Redgate SQL Toolbelt和Azure DevOps的持續整合

將為您建立一個新的管道,其預設名稱(在我的情況下為 StackOverflow-CI )和預設的代理佇列(在我的情況下, 託管VS2017 ,這是Azure DevOps的預設名稱。管道包含一個名為 AgentJob1 的預設作業,雖然如果你選擇它,你可以重新命名它。讓我們稱之為 Build Stack Overflow Database

資料庫與Redgate SQL Toolbelt和Azure DevOps的持續整合

我們可以將 任務 新增到將執行MSBuild或執行PowerShell指令碼等的 代理作業 ,以編譯和測試我們的程式碼。為此,請單擊代理作業旁邊的 + 按鈕。

資料庫與Redgate SQL Toolbelt和Azure DevOps的持續整合

Redgate SQL Change Automation Azure DevOps擴充套件預設不可用,但如果您在 新增任務 下的 Marketplace 選項卡中搜尋“Redgate”,您將找到它。按照說明新增 SQL Change Automation:Build 擴充套件。

安裝完成後,找到返回構建過程的方法。您可能需要再次點選上面的第2-5點,因為您的新定義可能尚未儲存。這一次,如果您搜尋“Redgate”,您會發現該擴充套件程式無需再次透過Marketplace即可使用,您只需單擊“  新增”即可

資料庫與Redgate SQL Toolbelt和Azure DevOps的持續整合

將在 Build StackOverflow資料庫 建立 構建 任務 ,並警告某些設定需要注意。單擊此構建任務,然後在“  操作” 下,選擇“  構建SQL原始碼管理”專案 。然後,在 Database資料夾下 選擇“  Database scripts資料夾是VCS根目錄的子資料夾  ”,在 Subfolder Path下 使用嚮導選擇由SQL Source Control維護的 狀態 目錄(不要選擇Git repo的根目錄) ,如果您按照步驟2.1,還將包含您的構建指令碼!)。

Output NuGet Package ID 下,為您的構建工件寫一個名稱。通常,這將是您的資料庫的名稱。

資料庫與Redgate SQL Toolbelt和Azure DevOps的持續整合

單擊“  儲存並排隊” 以手動觸發構建。預設設定應該沒問題。您應該看到一個黃色通知,表明構建已排隊。如果單擊該號碼,則會轉到實時構建日誌。

資料庫與Redgate SQL Toolbelt和Azure DevOps的持續整合

將為您分配託管代理。然後,它將下載SQL Change Automation並 localDB 在雲中自行構建原始碼並報告結果。

請注意,如果您的資料庫不構建在Azure中託管構建代理上的本地資料庫的預設安裝上,則構建將失敗。如果您的資料庫不能構建 localDB ,則需要提供一個單獨的SQL Server例項來執行構建。然後,在 Build StackOverflow Database 構建任務中,將 Temporary伺服器型別 SQL LocalDB(推薦) 更改為 SQL Server ,並向伺服器例項提供連線詳細資訊。如果要在本地託管此伺服器例項,則可能需要安裝可以訪問本地伺服器的本地構建代理來執行構建。

構建可能需要幾分鐘。就我而言,使用Stack Overflow和託管構建代理程式,花了大約兩分半鐘。使用更大,更復雜的模式,您可能需要更長時間。

資料庫與Redgate SQL Toolbelt和Azure DevOps的持續整合

如果構建失敗,請查詢日誌中的錯誤並進行故障排除。常見問題包括缺少依賴項,不正確的憑據,對資料庫的許可權不足,使用不受支援的功能 localDB 以及損壞的T-SQL程式碼。保持堵塞,直到你的構建變綠。如果您跳過步驟2.1並且在構建時遇到問題,請考慮返回並嘗試步驟2.1,因為這是解決原始碼問題的一種更簡單的方法,可以幫助您確定問題是否與原始碼或Azure DevOps配置。

一旦構建為綠色,您需要設定構建觸發器以確保每次將新程式碼推送到Azure DevOps伺服器時構建都會執行。從Azure DevOps中的任何頁面,將滑鼠懸停在頂部的“  管道” 選項卡上,然後選擇“  生成” 以導航回您的構建定義。選擇 Build Definition ,然後選擇 Edit 按鈕。

資料庫與Redgate SQL Toolbelt和Azure DevOps的持續整合

選擇 觸發器 並確保選中 啟用持續整合 ,您就完成了。

資料庫與Redgate SQL Toolbelt和Azure DevOps的持續整合

如果您已經做到這一點,並且將新程式碼推送到Azure DevOps,那麼它將自動啟動構建並驗證您的程式碼,並且您可以繼續持續整合並快速獲得有關錯誤的反饋。

進一步擴充套件

自動化資料庫構建只是第一步。所有這些都將測試您的原始碼是否可部署。它不會測試您的儲存過程是否按設計執行。它不會自動更新整合資料庫,因此它始終與源控制元件保持同步。它不會將您的程式碼部署到測試,登臺和生產伺服器。

首先,最重要的是,您需要開始編寫將在每次構建時自動執行的資料庫的測試。檢視tSQLt和Redgate SQL Test。

如果使用寫在PowerShell指令碼步驟2.1,並且已安裝資料庫的tSQLt框架,並致力於其原始碼管理,您可以透過下取消註釋行你構建的一部分執行測試 #執行測試 。如果您還沒有將tSQLt框架提交給原始碼控制,那麼這將失敗。您還應確保將 $ testPath 預設引數設定為git repo之外的現有目錄。與包一樣,每次執行構建時都需要覆蓋 $ packageVersion

如果您希望構建將更改部署到整合資料庫,請取消註釋#Sync  a test database 下的行並適當地設定 $ targetServerInstance 和$ targetDatabase 的預設值。

如果您在Azure DevOps中使用Redgate SQL Change Automation擴充套件,則需要:

  1. 新增 SQL Change Automation:Build 任務, 操作 設定為“使用tSQLt測試從SQL Source Control專案測試構建工件”。同樣,除非您已經在原始碼管理中使用了tSQLt框架和測試,否則這將無法工作。

  2. 新增 SQL Change Automation:Build 任務, 操作 設定為“將構建工件從SQL原始碼管理專案同步到目標資料庫”。



來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31557424/viewspace-2284748/,如需轉載,請註明出處,否則將追究法律責任。

相關文章