Team Foundation Server (TFS) 本質上是面向團隊的。當然,由一個人組成的團隊也可以使用它,但 TFS 實際上是針對與開發項目中其他人之間的協作。
構建自動化不再只是按 F5。構建自動化涉及的是收集、匯編、驗證和審核。其要旨就是收集組成解決 方案的所有產物,然後根據定義明確的集成計劃將這些產物進行匯編。編譯是在匯編階段中定義的典型任 務。您可以使用各種自動化測試(通常使用構建驗證測試 (BVT) 或冒煙測試)來驗證團隊的集體作品。
最後,您需要執行某些類型的審核來評估構建的整體質量。審核流程所提供的數據可幫助您解答 各種棘手的問題。例如,截至此構建的各功能是否能創造一個產品?產品是否具備高質量?是否出現了某 些退步?是否是按照日程表完成工作?構建審核的價值在於使您可以輕松地掌握團隊工作情況。
在本專欄中,我將向您介紹 Visual Studio 2008 Team Foundation Server Build (Team Build),並帶 您了解創建和運行 Team Build 的過程。我還將展示目前可供您用於針對 Team Build 2008 進行編程的 托管 API。
關於 Team Build
Team Build 是 TFS 2008 的核心功能。Microsoft 旨在將其 打造為行業強勢構建自動化工具。可以說它為您的團隊提供了 F5 體驗。在典型環境中,您將在其專用的 服務器上安裝 Team Build(如果您的團隊非常小或預算很緊張,則可以在 TFS 上安裝 Team Build)。
2008 版本的 Team Build 是一次較大的更新,這一點與 TFS 的其他部分不同。在 2005 版本中 ,Microsoft 打造了一款優秀的構建自動化產品。Team Build 2005 利用 MS-Build 作為其引擎,支持多 項您所期望的核心自動化功能:版本控制、編譯、多構建類型、單元測試、靜態分析和代碼覆蓋。
此外,它還提供卓越的報告功能,包括構建報告和對 TFS 數據倉庫的數據更新,以支持歷史趨勢 分析。2005 版本的 Team Build 還支持多構建計算機、構建通知以及從命令行或通過團隊資源管理器用 戶界面啟動構建。
在 Team Build 2008 中,Microsoft 做出了更深層次的改進。主要的增強功能 包括持續集成支持、構建排隊、通過“團隊資源管理器”安排構建日程以及托管對象模型。此 外,Microsoft 將構建代理定義與構建定義分離,創建了一個構建定義編輯用戶界面,並添加了更高效的 構建管理工具。
與穩健的 Team Build 2005 功能集相結合後,Team Build 2008 呈現了一個引人 注目的構建自動化解決方案。此外,由於 Microsoft 繼續支持向後兼容性,因此,即使開發團隊仍在使 用 Visual Studio 2005,您也可以升級 TFS 安裝和 Team Build 服務器。
創建 Team Build
要使用 Team Build,您自然需要安裝 TFS,單個服務器或雙服務器配置皆可。您需要已安 裝 Team Build 並正確配置您的構建服務器。有關詳細信息,請參閱最近更新的 Team Foundation 安裝 指南。最後,您還需要一個已將某些代碼簽入版本控制庫的團隊項目。
在安裝了 Team Foundation 服務器客戶端的 Visual Studio 2008 中,打開加載了您的團隊項目的 “團隊資源管理器”窗口。在本示例中,假定您已使用 MSF-Agile 模板創建了一個名為 MSDNMag 的團隊項目。(如果您希望向下繼續進行,可從本專欄及 Team System 2008 TFS 和 Team Suite 虛擬 PC 映像下載代碼。)本例使用一個名為 MSDNMag 的自定義工作區,並將樹干映射到虛擬 PC 映像中的 C:\Work。
完成上述所有操作後,可以在“團隊資源管理器”窗口中展開 MSDNMag 團隊項目節點並找 到 Builds 文件夾。如果右鍵單擊 Builds 文件夾,會顯示出很多選項。此時您應關注的是“New Build Definition”(新建構建定義)命令。選中該選項後,隨即顯示“Build Definition”(構建定義)對話框(請參見圖 1)。
圖 1 空白的 “Build Definition”(構建定義)對話框
與 Team Build 2005 中的向導不同,在您 需要編輯某個構建定義時可以返回此對話框。首先要提供構建名稱,例如 SimpleBuildExplorer- OnDemand。另外,您可以通過選中“Disable This Build Definition”(禁用該構建定義) 選項使該構建保持離線狀態。
創建新構建時,您必須提供構建定義名稱和 Team Build 項目文件 ,並指定構建代理和放置位置。也就是說,我認為第二個選項“Workspace”(工作區)很關 鍵。
在 Team Build 2005 中,“Workspace”(工作區)選項是您必須了解的選項。 實現細節已經發生了更改,但用途保持不變:限制 Team Build 在構建中獲取資源時下載的產物。在 Team Build 2005 中,您需要修改一個名為 WorkspaceMapping.xml 的文件。在 Team Build 2008 中, 可使用與工作區映射對話框中類似的 GUI 來進行版本控制(請參見圖 2)。
圖 2 “Build Definition”(構建定義)對話框的工作區頁面
通過工作區可定義將源代碼庫的哪些內容用 作構建的組成部分。默認情況下,Team Build 將團隊項目的樹干映射到構建所使用的源下載位置(運行 構建的代理與構建定義相關聯時可以控制的要素)。有一點需要明確,如果您不調整此設置,則每次執行 構建時,Team Build 都會對樹干執行一個 get 命令,從而獲取一切最新內容。在您進行演示或測試時這 算不上什麼大事,但一旦您在團隊項目和多個分支中要從事半年的工作,則最好不要通過此方式運行構建 。
即使此處的演示場景只有一個 Visual Studio 解決方案,您也應該調整該映射。單擊 “Source Control Folder”(源代碼管理文件夾)列下的第一項時,您可以選擇鍵入一個受 限路徑,也可以使用“Browse for Folder”(浏覽文件夾)對話框。在本例中,我將 “Source Control Folder”(源代碼管理文件夾)設置為 $/MSDNMag/Main/src/TeamSystem/C08。
就像在用於版本控制工作區映射的對話框中一樣,您可以 定義多個文件夾映射。變量 $(SourceDir) 是 Team Build 擴展到構建目錄的環境變量,在構建代理屬性 對話框中為構建代理指定該目錄。通常您要使用的是 $(SourceDir),以便路徑為相對路徑。但 Team Build 並不強制您使用它。在本例中,我將其保持原樣。
最後,如果您現有工作區中的所有映射 都按照您的期望進行的配置,則您可以使用“Copy Existing Workspace”(復制現有工作區 )選項復制映射的版本控制文件夾部分,從而節省您的時間。
在定義了工作區設置後,您需要定 義構建項目文件。單擊“Project File”(項目文件)選項時,您可以提供已在版本控制下的 現有 TFSBuild.proj 文件的路徑。TFSBuild.proj 是 2005 版本中包含所有構建配置數據的 XML 文件, 也是用戶進行定制以增強實際構建過程的文件。Team Build 2008 在構建定制中繼續使用該文件,但與構 建定義相關的大多數數據均存儲在 TFS 數據庫中。如果您還沒有該文件,可單擊“Create” (創建)按鈕並使用簡單向導構建一個文件。
Team Build 2008 中的一個重大變化是您現在可以 自己指定 TFSBuild.proj 文件的存儲位置。在 Team Build 2005 中,Microsoft 會將該路徑硬編碼為版 本控制庫中某個特定位置。默認情況下,Team Build 2008 對話框指定一個與 Team Build 2005 兼容的 路徑,形式為 %TeamProjectName%/TeamBuildTypes/%BuildDefinitionName%。
在本例中,為所提 議的版本控制文件夾指定的路徑是 $/MSDNMag/TeamBuildTypes/SimpleBuildExplorer-OnDemand。能夠更 改路徑的最大好處是現在可以用其他產物來擴充 TFSBuild.proj 文件。在本例中,接受默認路徑,然後 單擊“Create”(創建)按鈕。
單擊“Create”(創建)按鈕時,Team Build 會顯示一個向導。該向導是從 Team Build 2005 版本保留下來的少數 UI 之一。第一個頁面會請 您選擇要構建的 Visual Studio 解決方案。該向導會對顯示的列表進行篩選,僅顯示那些相對於您的工 作區映射可用的解決方案。如果不更改默認的工作區映射,您會看到團隊項目中的所有解決方案。選擇所 提供的單個解決方案,然後單擊“Next”(下一步)。
向導的第二頁用於選擇要構建 的 Visual Studio 配置類型。盡管該向導僅提供了“Debug”(調試)和 “Release”(發布)類型的配置,但您可以輸入自定義配置。該規則同樣適用於“平台 ”。接受默認選項,然後單擊“Next”(下一步)。
向導的最後一頁可用於控制 測試和靜態分析執行。需要在構建代理計算機上安裝 VSTS 才能使測試執行和靜態分析正常進行。與在 Team Build 2005 版本中一樣,您也可以選擇測試元數據文件,並從中選擇任何支持無人參與執行的測試 列表。但您也可以選擇讓 Team Build 自動掃描您的輸出程序集以找出與 MSTest 兼容的測試,並在沒有 測試列表的情況下運行這些測試。如果您已在一個或多個 Visual Studio 項目中啟用了靜態分析,則可 以讓 Team Build 執行靜態分析。本專欄中的示例解決方案不包含任何測試或靜態分析,因此單擊 “Finish”(完成)結束該向導並創建 TFSBuild.proj 文件。
此時,您只需要完成構 建默認設置即可。首先,我們來看一看保留策略和觸發器設置。Team Build 2008 超越 Team Build 2005 版本的一個重大改進就是現在允許您根據每個構建定義來配置保留策略(請參見圖 3)。根據特定構建的 結果,您可以控制 Team Build 保留多少構建結果。
圖 3 控制構建定義保留 策略
構建完成後,您可以對構建結果作出標記,這樣 Team Build 就可以忽略保留策略而將其保 存。在本例中要注意的是,您應將保留策略設置為默認值。
如果您在 Team Build 2008 中單擊 “Trigger”(觸發器)選項,則它會像 Team Build 2005 一樣僅在您要求時才運行構建。但 您將注意到,Team Build 現在也支持持續集成 (CI)。(有關 CI 的詳細信息,請參閱 2008 年 3 月的 文章“使用持續集成重新定義構建過程”。)這意味著,只要有人簽入對構建定義的工作區映 射所映射的文件的更改,就會有一個構建排入隊列。該對話框以“Build each check-in (more builds)”(構建每個簽入(更多構建))選項表明了這一點。
第二個選項 “Accumulate check-ins until the prior build finishes (fewer builds)”(累積簽入, 直到上一個構建完成(更少構建))可提供延遲形式的 CI。最後一個選項可使您配置按日程表執行的構 建(請參見圖 4)。
圖 4 將 Team Build 配 置為按日程表執行構建
您應保留觸發器的默認設置,即簽入不觸發新構建,然後選擇 “Build Defaults”(構建默認值)選項。使用構建默認值指定要使用的構建代理以及構建輸 出的放置位置。您可以使用 UNC 路徑指定放置位置。如果使用 Microsoft 提供的虛擬 PC 映像,則可以 輸入 \\localhost\Drops\MSDNMag\SimpleBuildExplorer-OnDemand。僅需要存在共享項。Team Build 將 在必要時創建額外的子文件夾。Team Build 將使用構建號在此路徑下創建一個文件夾。
創建共享項時,您需要確保分配了正確的權限。Team Build 和 TFS 服務帳戶至少需要具備對共享項 的“完全控制”權限。此外,您需要向負責發布與構建相關的測試結果的人員賦予“寫 入”權限。您應向需要獲取已完成構建的人員賦予“讀取”權限。
假定已完成了 共享配置,則需要指定構建代理。如果您已經定義了某個構建代理,可從組合框中選擇它。如果沒有定義 ,則可以單擊“New”(新建)按鈕,這將打開標准的“Build Agent Properties”(構建代理屬性)對話框。在本例中,您需要定義新代理,因此請單擊 “New”(新建)。
創建構建代理
與 Team Build 2005 版本不同,Team Build 2008 構建代理獨立於構建定義。定義了某代理後,您很容易就可以再次使用它。通過“Build Agent Properties”(構建代理屬性)對話框可以定義與該代理相關的所有關鍵屬性。首先需要提 供顯示名稱和可選的說明。然後以 NETBIOS 或 DNS 名稱的形式提供計算機名稱。顯示名稱和計算機名稱 可以完全不同。如果使用的是 SSL,則可以指定該選項。
一個關鍵設置就是工作目錄。默認情況 下,它使用的路徑形式為 $(Temp)\$(BuildDefinitionPath)。盡管這對於多數構建都有效,但會由於令 人生畏的 MAX_PATH 問題導致故障。Windows Server 2003 計算機上的 $Temp 將是 %SystemDrive% \Documents and Settings\<build agent service account>\Local Settings\Temp。字符實在太 多了。我通常建議人們將其改短一些,尤其是在構建數據庫專業版本時。在本示例中,將工作目錄更改為 C:\Builds\$(BuildDefinitionPath)。
最後,您可以控制該代理的狀態。這對於維護特別有用。此外,如果 TFS 無法聯系某個構建代理,則 會將代理的狀態更改為無法訪問,這樣,在管理員更改設置前就會阻止使用該代理。將該設置保留為啟用 狀態,然後單擊“OK”(確定)關閉完成的“Build Agent Properties”(構建代 理屬性)對話框(請參見圖 5)。返回“Build Definition”(構建定義)對話框,所有的三 角形警告標志都將消失,您可單擊“OK”(確定)完成構建定義。
圖 5 已完成的“ 構建代理屬性”對話框
在“團隊資源管理器”窗口的 Builds 文件夾下,您將看到您創建的構建定義。如果右鍵單擊該定義 ,則可以看到一個“Edit Build Definition”(編輯構建定義)選項,通過該選項可以返回到剛剛用過 的“Build Definition”(構建定義)對話框。此外,您還可以使用“Queue New Build”(排隊新構建 )選項使新構建排隊。
與 Team Build 2005 不同,Team Build 2008 現在支持構建的排隊,如果 Microsoft 要完全支持持 續集成,這是一項必要功能。選擇此選項後,將打開“Queue Build”(排隊構建)對話框(請參見圖 6 ),您可以調整幾個選項。首先,您可以根據需要輕松地將默認構建代理更改為替代項。其次,您可以調 整放置位置。此外,您可以通過調整“Priority in queue”(隊列中的優先級)選項使某個特定構建“ 插隊”。最後,如果用戶具有“管理構建”權限,則還可以傳遞 MSBuild 命令行參數。
圖 6 “Queue Build”(排隊構建)對話框
運行 Team Build
單擊“Queue”(隊列)以啟動構建。執行此操作時,將打開更新的“Build Explorer”(構建資源管 理器)窗口。該窗口有兩個主選項卡。默認情況下,“已排隊”(Queued)選項卡將顯示所有已排隊的構 建,而不考慮其代理或狀態是什麼。您會看到幾個組合框,用於根據構建定義、構建狀態或構建代理來調 整“構建資源管理器”將顯示哪些構建。
“已完成”(Completed)選項卡將顯示已完成的構建並支持相同類型的篩選。啟動構建時,可雙擊構 建以查看實時構建報告。Team Build 會在整個構建過程中實時更新此報告。
運行 Team Build 時,會發生很多操作。TFS 從隊列中啟動該構建後,構建代理就已准備好運行該構 建。TFS 將創建一個構建號,構建代理會將源代碼與構建定義中指定的位置同步。該代理隨後將編譯這些 代碼並在必要時運行代碼分析。然後構建代理將運行測試。然後該代理會運行一個用於更新與該構建號關 聯的所有工作項的任務。
例如,MSF-Agile 模板中的默認任務工作項具有一個 Team Build 更新的“Integration Build”(集 成構建)字段。該代理將計算代碼覆蓋率(如果將測試配置為作為構建的一部分運行且啟用了代碼覆蓋) 並確定上一個合格構建(編譯成功)與當前構建之間的所有更改集。它會將文件復制到放置共享、將構建 結果公布給 TFS,而 TFS 會觸發一個構建完成事件。有關 TFS 事件的詳細信息,請參閱本人的 2008 年 5 月專欄。
Microsoft 在 Team Build 2008 中作出了兩個與測試和工作項相關的重要變更。第一個變化是如果構 建出現一次或多次測試失敗,並不算做構建失敗。 與在 Team Build 2005 中一樣,具有一個或多個失敗 測試的構建將顯示為“部分完成”,而不是“失敗”。其次,在 Team Build 2005 中,在第一次運行構 建時,Team Build 會列出自團隊項目開始以來在第一個構建報告中構建的所有工作項以及與工作項相關 的更改集。Team Build 2008 僅在構建第一次成功運行後才開始顯示和更新工作項。在我的下個專欄中, 我將介紹如何通過構建定制來調整這些行為。
Team Build 編程
Team Build 2008 中最明顯的增強功能之一就是添加了托管 API。
Microsoft.TeamFoundation.Build.Client.dll 是您將使用的主要程序集。本專欄的示例應用程序引 用了此程序集以及 Microsoft.TeamFoundation.Client.dll 和 Microsoft.TeamFoundation.VersionControl.Client.dll 程序集。
該示例應用程序是一個運用某種新 APL 的簡單的 Windows 窗體應用程序。該應用程序與 TFS 連接並 枚舉了所有團隊項目的列表,從而將它們加載到樹視圖控件中。在各個團隊項目下,它將添加“Build Agents”(構建代理)和“Build Definitions”(構建定義)節點(請參見圖 7)。
圖 7 示例應用程序
展開某節點時,TreeNode 的 BeforeExpand 事件中的代碼將運行並枚舉可用的構建代理、構建定義或 已完成的構建,這具體取決於您已展開的節點。此外,主窗體承載了一個“Property Grid”(屬性網格 )控件。在選擇具有非空標記值的節點時,該應用程序會將引用對象加載到“Property Grid”(屬性網 格)的 SelectedObject 屬性中。圖 7 顯示了已展開 MSDNMag 團隊項目並選定了主構建代理的應用程序 。
應用程序的大部分都是簡單的枚舉代碼。但它卻具有一個 Microsoft 在“團隊資源管理器”沒有體 現的功能。當您定義某構建代理時,TFS 會將構建代理的范圍限定在該特定團隊項目。但我發現很多組織 僅有一個或兩個構建代理。這意味著他們必須多次重新創建構建代理。使用示例應用程序時,如果右鍵單 擊某構建代理實例,將顯示一個上下文菜單以及一個“Copy Agent To”(將代理復制到)命令(請參見 圖 8)。
圖 8 Copy Agent To(將代理復制到)命令
選擇此選項會打開一個對話框,該對話框用於選擇要將構建代理定義復制到的團隊項目。所有相關的 代碼均在圖 9 所示的CopyAgentToToolStripMenuItem_Click 事件處理程序中。
圖 9 CopyAgentToToolStripMenuItem_Click 方法
Private Sub CopyAgentToToolStripMenuItem_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles CopyAgentToToolStripMenuItem.Click Dim current As TreeNode = tv.SelectedNode Dim ba As IBuildAgent = _ TryCast(current.Tag, IBuildAgent) If ba Is Nothing Then Exit Sub Dim parentProject As String = ba.TeamProject Using frm As New frmPickProject frm.cboProjects.DataSource = _ (From item In teamProjectNames _ Where item <> parentProject _ Select item).ToArray() If frm.ShowDialog(Me) = Windows.Forms.DialogResult.OK Then Dim teamProjectName As String = _ frm.cboProjects.SelectedItem.ToString() Dim existingAgent = _ (From item As IBuildAgent In _ m_bs.QueryBuildAgents(teamProjectName) _ Where item.Name = ba.Name).SingleOrDefault If existingAgent Is Nothing Then Dim newBuildAgent As IBuildAgent = _ ba.CopyTo(teamProjectName) newBuildAgent.Save() MessageBox.Show(newBuildAgent.Name & " copied.") Else MessageBox.Show(existingAgent.Name & " already exists.") End If End If End Using End Sub
假定選定的代碼將某標記設置為 IBuildAgent 引用,該代碼將顯示 frmPickProject 窗體。此窗體包 含一個顯示所有可用團隊項目(當前構建代理的團隊項目除外)的組合框。
該代碼對所有團隊項目名稱(您第一次展開樹視圖根項時所收集的)字符串陣列執行 LINQ 查詢,以 此填充該組合框的數據源。假定您選擇了某團隊項目並在項目選擇窗體中單擊“OK”(確定),該代碼會 運行 LINQ 查詢以驗證目標團隊項目是否有同名的構建代理。如果發現一個同名的構建代理,則會顯示一 條消息。但如果沒有發現,它將復制該構建代理定義。
特別要注意的是,Microsoft 提供了一種 CopyTo 方法。當我最初設計出該代碼時,我計劃對新的 IBuildAgent 實例執行逐個屬性的復制。這看起來就像 Microsoft 引入了 API 但未添加到用戶界面一樣 。
希望您能感受到 Team Build 2008 是一款行業強勢構建產品。如果您目前正在使用 Team Build 2005 ,則升級到 Team Build 2008 會為您增加很多價值。在我的下個專欄中,我將深入探討構建定制以及如 何使您的構建不僅能編譯解決方案,還可以部署到測試環境中等內容。
衷心感謝 Ken Getz 和 Martin Woodward 對本期專欄的大力支持。
請將您想向 Brian 詢問的問題和提出的意見發送至 [email protected]。
Brian A. Randell 是 MCW Technologies LLC 的一名高級顧問。他主要從事 Microsoft 技術方面的 講解、培訓和撰寫工作。Brian 是 Pluralsight 的 Applied Team System 課程的作者,同時也是 Microsoft MVP。您可以通過 Brian 的博客 mcwtech.com/cs/blogs/brianr 與他聯系。
本文配套源碼:http://www.bianceng.net/dotnet/201212/771.htm