愛流浪的小風

技術隨手寫

[Tool] 使用Travis CI自動建置.Net Open Source Project並發佈到Nuget上

| Comments

微軟在Build 2014開發者大會上宣佈釋出包含.NET Compiler平台在內等多項開發技術,同時也將.Net的原始碼在Github上公開(網址:https://github.com/Microsoft/dotnet),所有人都可以替.Net原始碼提供自己的一份心力。隨著Open Source越來越普及,公開自己開發的Library不但可以幫助其他人不需要重複造輪子,甚至可以透過開放社群的力量,共同來讓熟悉的語言擁有更好用的工具,剛好我們公司最近也將陸陸續續的開放一些專案到Github上提供給需要的人員一起使用,在這邊分享我們如何透過Open Source的服務來自動建置、測試並發佈成品到Nuget上供大家使用。

使用Travis CI建置專案

Travis CI是一套專門為開放程式碼打造的Continuous Integration Server,可以幫助我們在有新的Commit或Pull Request時,自動建置並測試專案,確保大家Commit到Github上的程式碼都是正確並通過測試的,避免新的Commit造成專案不能建置或改壞功能的情形發生。(當然如果是考量到企業內部使用,或是需要更完整的.Net建置資源,使用Visual Studio Online是更棒的選擇。)

首先向大家介紹,如何透過Travis CI來建置我們的.Net專案。

  1. 準備好自己的Open Source專案,並Check In到Github上

  2. 進入Travis CI官方網站,由於要需要讀取Github上的程式碼,所以我們必須使用Github帳號來登入

  3. 第一次登入會需要授權,登入成功後可以看到下面的畫面,在右上角選擇Account,如果沒有看到自己在Github的帳號的話,可以手動點選Sync now,成功後可以看到自己在Github上的專案清單

  4. 將自己想要進行建置的專案狀態由off切為on

  5. 回到自己的Open Source專案之中,在根目錄新增Travis CI建置所需要的設定檔.travis.yml如下,由於Travis CI建置的環境其實是Linux base,所以我們在這邊沒辦法直接使用msbuild來建置專案,而是透過Mono來在Linux上建置專案

    install部分的語法是CI初始化時,需安裝建置所需要的環境(包含Mono的安裝)

    script部分是真正建置專案使用的語法,類似msbuild,指定sln的名稱

    language: c
    
    install:
    # 使用mono進行建置
    - sudo add-apt-repository ppa:directhex/monoxide -y && sudo apt-get update
    - sudo apt-get install mono-devel mono-gmcs
    - mozroots --import --sync
    
    script:
    # 修改為自己專案的sln名稱
    - xbuild NSquared.AspNet.Extensions.sln 
    
    env:
    global:
    - EnableNuGetPackageRestore=true
    
  6. 新增完設定檔後,push到github上,回到Travis CI,可以看到我們多了一個待建置的Commit,這代表我們的建置工作已經被排入執行的Queue中,準備開始執行

  7. 等待一小段時間後,可以看到專案成功的建置,透過這樣的設定,我們就可以確保每一次的Commit都會讓Travis CI跑一次建置,確保程式碼是可執行的

  8. Travis CI還提供了開源專案一個建置狀態的小貼紙,方便我們在Github上顯示專案的健康狀態,我們可以透過點擊右上角的build圖案,取得自動產生圖片的網址

  9. 我們可以把這個狀態貼紙加到我們Github專案的Readme上,這樣別人只要一進入我們的專案,就可以看到專案是否能建置通過囉!

進行單元測試

在進行一個OpenSource專案時,單元測試也是很重要的,它可以幫助每一個新參與的開發者,快速的確認他們所增加的功能並沒有影響原本支援的功能,也可以讓人更盡情的發揮自己的想像力,讓這個Library更加的好使用,下面我就要像大家介紹如何在Travis CI上加上單元測試

  1. 首先先替程式碼加上單元測試,在這邊我所使用的是Specflow這套BDD Framework,它可以幫助我們將測試案例用更語意化的文字來說明測試內容

    ※ 更多測試的文章可以參考91的部落格

  2. 在專案中加上BuildScripts/unittest.sh,我在這邊是使用specrun.exe來幫助我進行specflow的單元測試,但由於在Linux系統上,所以透過mono來執行

    #!/bin/bash
    # 使用Nuget安裝Specrun
    mono --runtime=v4.0.30319 .nuget/NuGet.exe install .nuget/packages.config -o packages
    # 使用Specfun執行測試
    mono --runtime=v4.0.30319 packages/SpecRun.Runner.1.2.0/tools/SpecRun.exe run NSquared.MvcExtensions.Test.dll /baseFolder:MvcExtensions.Test/bin/Debug /toolIntegration:vs2010 /reportFile:.\TestReport.html
    
  3. 到.travis.yml中增加執行unittest.sh,讓建置時同時執行單元測試

    language: c
    
    install:
    - sudo add-apt-repository ppa:directhex/monoxide -y && sudo apt-get update
    - sudo apt-get install mono-devel mono-gmcs
    - mozroots --import --sync
    
    script:
    - xbuild NSquared.AspNet.Extensions.sln
    # 進行單元測試
    - bash BuildScripts/unittest.sh  
    
    env:
        global:
        - EnableNuGetPackageRestore=true 
    
  4. 都修改完畢後,一樣push到github上,就可以看到Travis CI建置的同時,也執行單元測試確保程式沒有壞囉!

將Library發佈到Nuget

有了自動建置和單元測試之後,就要進行將專案建置的結果打包並發行到Nuget上,在發行到Nuget之前,我們必須先準備好申請一組Nuget帳號和Api Key,大家可以到Nuget官方網站申請,下面就開始介紹我們打包Nuget的步驟。

  1. 在開始打包Nuget之前,我們必須先準備好一份定義檔(*.nuspec),可以使用Nuget Package Explorer來產生,這個檔案主要是說明專案的Dependency和要打包的內容

    使用Nuget Package Explorer產生的定義檔

    定義檔原始內容

    <?xml version="1.0" encoding="utf-8"?>
    <package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
        <metadata>
            <id>NSquared.MvcExtensions</id>
            <version>1.0.0</version>
            <title>NSquared.MvcExtensions</title>
            <authors>NSquared</authors>
            <projectUrl>https://github.com/91mai/NSquared.AspNet.Extensions</projectUrl>
            <iconUrl>https://avatars0.githubusercontent.com/u/10022788?v=3&amp;s=200</iconUrl>
            <requireLicenseAcceptance>false</requireLicenseAcceptance>
            <description>This is a Asp.Net Extension for Asp.Net Mvc or Asp.Net WebApi. For easily extend by Action Filter or otherwise.</description>
            <language>zh-TW</language>
            <dependencies>
                <group targetFramework=".NETFramework4.5">
                    <dependency id="Microsoft.AspNet.Mvc" version="4.0.40804.0" />
                    <dependency id="Newtonsoft.Json" version="5.0.8" />
                </group>
            </dependencies>
        </metadata>
        <files>/
            <file src="/MvcExtensions/bin/Debug/NSquared.MvcExtensions.dll" target="lib\net45\NSquared.MvcExtensions.dll" />
        </files>
    </package>
    

    這邊需要注意的是,由於Linux系統的檔案路徑和windows不一樣,所以要將檔案路徑的\換成/

  2. 到Nuget的帳號資訊頁面,記下ApiKey

  3. 加密Api Key,並存到.travis CI設定檔中,必須先安裝Travis CI的gem (詳細說明),安裝完成之後,使用Command Line切換至專案的根目錄,並輸入以下指令加密Api Key到.travis.yml中

    travis encrypt -r 91mai/NSquared.AspNet.Extensions NUGET_APIKEY=<token> --add env.global
    
  4. 執行完成後,開啟.travis.yml應該可以看到多了一個加密區段,這樣可以避免我們將專案存在Github上,但某些Api Key也暴露出來,造成安全問題

  5. 新增BuildScripts/deploypackage.sh,使用nuget指令打包到官方nuget repository中,並自動根據Travis CI的Build Number增加版號,同時因為不希望所有的commit都會打包Nuget Package,這邊也增加判斷只有在Master Branch的commit會打包至nuget! (這邊因為是測試版本,所以版號加上-alpha,nuget會自動判斷為prerelease版本)

    #!/bin/bash
    VersionNumber="0.0.${TRAVIS_BUILD_NUMBER}-alpha"
    
    echo "VersionNumber: $VersionNumber"
    
    if [ "$TRAVIS_BRANCH" == "master" ]; then         
        mono --runtime=v4.0.30319 .nuget/NuGet.exe Pack NSquared.MvcExtensions.nuspec -NonInteractive -Version ${VersionNumber}
        mono --runtime=v4.0.30319 .nuget/NuGet.exe Push NSquared.MvcExtensions.${VersionNumber}.nupkg $NUGET_APIKEY -NonInteractive     
    fi
    
  6. 在.travis.yml一樣增加執行打包至nuget的指令

  7. 設定完畢後,一樣push到Github上,等待Travis CI自動執行

  8. 到Nuget官方網站上,也可以看到已經成功發佈Package

小結

我們的Open Source Project使用Github進行版本控制,每當有新的Commit或Pull Request時就會透過Travis CI進行建置,並經過單元測試,讓大家可以放心開發,一旦有錯誤影響功能就會馬上被發現。當我們需要Release新版本時,只需要將develop Branch Merge到master,Travis CI就會自動幫我們發佈最新版本的Package到Nuget上,使用者也就可以馬上更新到最新版囉!

Comments

comments powered by Disqus