2012-10-18 83 views
3

我剛剛加入了一個沒有CI過程的團隊(甚至沒有過夜編譯)和一些粗略的開發實踐。我們希望改變這種狀況,所以我現在的任務是創造一夜之間的構建。我一直在跟着this series的文章來:創建一個包含我們所有項目(一些Web應用程序,一個Web服務,一些Windows服務,以及編譯到命令行可執行文件的工具)的主解決方案;創建了一個MSBuild腳本來自動構建,打包和部署我們的產品;並創建一個.cmd文件來完成一次點擊。這是我現在試圖完成的一項任務,作爲所有這些的一部分:使用MSBuild批量重命名

該團隊目前有一種做法,將web.config和app.config文件保存在源代碼管理之外,並將其放入源代碼管理文件稱爲web.template.config和app.template.config。其目的是開發人員將.template.config文件複製到.config以獲取所有標準配置值,然後能夠編輯.config文件中的值以滿足本地開發/測試所需的任何內容。出於顯而易見的原因,我想自動將.template.config文件重命名爲.config。什麼是最好的方法來做到這一點?

是否有可能在構建腳本本身執行此操作,而無需在腳本中規定需要重命名的每個單獨文件(這將需要在腳本添加到解決方案時隨時維護腳本) ?或者我可能需要編寫一些我從腳本中運行的批處理文件?

此外,有沒有更好的開發解決方案,我可以建議,這將使整個過程不必要?

+0

爲什麼配置文件沒有簽到?您能提供一些特定於開發人員(並且不能共享)的配置設置的示例嗎? –

+0

據我所知,沒有使用無法共享的設置。但是開發人員可能想要更改連接字符串,以便他可以對本地數據庫執行所有測試。我可以告訴你,當前的過程很糟糕,因爲項目文件仍然期望有一個web.config文件,這增加了我不得不做的所有工作的手動工作量。 –

+0

整個團隊(只有3或4個開發人員,直到我加入)似乎沒有現狀的問題,因爲開發人員似乎對特定項目擁有很大的所有權,甚至可能不會構建其他'。因此,他們只處理單個項目文件,而不是像我創建的主解決方案那樣。 –

回答

5

經過大量關於物品組,目標和複印任務的閱讀後,我已經想出瞭如何去做我所需要的。

<ItemGroup> 
    <FilesToCopy Include="..\**\app.template.config"> 
     <NewFilename>app.config</NewFilename> 
    </FilesToCopy> 
    <FilesToCopy Include="..\**\web.template.config"> 
     <NewFilename>web.config</NewFilename> 
    </FilesToCopy> 
    <FilesToCopy Include"..\Hibernate\hibernate.cfg.template.xml"> 
     <NewFilename>hibernate.cfg.xml</NewFilename> 
    </FilesToCopy> 
</ItemGroup> 

<Target Name="CopyFiles" 
     Inputs="@(FilesToCopy)" 
     Outputs="@(FilesToCopy->'%(RootDir)%(Directory)%(NewFilename)')"> 
    <Message Text="Copying *.template.config files to *.config"/> 
<Copy SourceFiles="@(FilesToCopy)" 
     DestinationFiles="@(FilesToCopy->'%(RootDir)%(Directory)%(NewFilename)')"/> 



我創建一個包含我要複製的文件的項目組。 **運算符告訴它遍歷整個目錄樹來查找具有指定名稱的每個文件。然後,我爲每個名爲「NewFilename」的文件添加一段元數據。這是我將重命名每個文件。

這段代碼加在指定app.template.config目錄結構的每個文件,並指定我將命名新文件的app.config:

<FilesToCopy Include="..\**\app.template.config"> 
    <NewFilename>app.config</NewFilename> 
</FilesToCopy> 

我然後創建一個目標複製所有的文件。該目標最初非常簡單,只調用複製任務以便始終複製和覆蓋文件。我傳遞FilesToCopy項目組作爲複製操作的來源。我使用transforms來指定輸出文件名,以及我的NewFilename元數據和衆所周知的項目元數據。

以下片段將例如將文件c:\ Project \ Subdir \ app.template.config轉換爲c:\ Project \ Subdir \ app。配置和複製前者向後者:

<Target Name="CopyFiles"> 
    <Copy SourceFiles="@(FilesToCopy)" 
      DestinationFiles="@(FilesToCopy->'%(RootDir)%(Directory)%(NewFileName)')"/> 
</Target> 

但後來我發現,開發者可能不希望有他定製的web.config文件被過度編寫的所有腳本運行時間。然而,如果存儲庫的web.template.config已被修改,開發人員可能會應該覆蓋他的本地文件,並且現在具有代碼需要的新值。我嘗試了許多不同的方法 - 使用「Exist()」函數將Copy屬性「SkipUnchangedFiles」設置爲true,但無濟於事。

對此的解決方案是building incrementally。這可確保只有在app.template.config更新時纔會覆蓋文件。我通過文件作爲目標輸入的名字,我指定新的文件名作爲目標輸出:

<Target Name="CopyFiles" 
     Input="@(FilesToCopy)" 
     Output="@(FilesToCopy->'%(RootDir)%(Directory)%(NewFileName)')"> 
     ... 
</Target> 

這樣做的目標檢查,看是否電流輸出上最新與尊重到輸入。如果不是,即特定的.template.config文件比其對應的.config文件具有更新的更改,則它會將web.template.config複製到現有的web.config上。否則,它將使開發人員的web.config文件保持原樣並保持不變。如果沒有指定的文件需要被複制,那麼目標被完全跳過。在乾淨的存儲庫克隆後立即複製每個文件。

上述結果是一個令人滿意的解決方案,因爲我只開始使用MSBuild,而且我對它強大的功能感到驚訝。我不喜歡的唯一的事情就是我必須在兩個地方重複完全相同的變換。我討厭重複任何形式的代碼,但我無法弄清楚如何避免這種情況。如果任何人有小費,將不勝感激。另外,雖然我認爲開發實踐需要這樣做,但這確實有助於緩解這種吸引因素。

+0

名稱爲「CopyFiles」的Target將自動調用?或者我必須做一些事情來包括那個目標? –

+0

假設您運行的是其他目標,例如「Build」,並且你希望這個目標作爲它的一部分運行,你需要使CopyFiles成爲目標的一個依賴項,如下所示:

1

簡短回答:
是的,你可以(也應該)自動化這個。您應該可以使用MSBuild Move task重命名文件。

龍答:
這是偉大的,有從手工工藝改變爲一個自動的願望。通常很少有原因不能實現自動化。您的構建腳本將作爲構建和部署實際工作方式的生動文檔。在我看來,一個好的構建腳本比靜態文檔更有價值(儘管我並不是說你不應該有文檔 - 畢竟它們是而不是)。讓我們分別討論你的問題。

這樣做的最好方法是什麼?

我並不完全瞭解這些文件中存儲的配置,但我懷疑可以在整個開發團隊中共享很多配置。

我建議提出以下問題:

  • 其中的設置是開發者的具體情況?
  • 有沒有什麼辦法來標準化本地開發人員機器,以便可以共享設置?

是否有可能做到這一點在構建腳本本身,而不必在腳本中規定,需要被重新命名每個單獨的文件?

是的,看看MSBuild Move task。您應該可以使用它來重命名文件。

...哪些需要在腳本中隨時添加新項目才能對腳本進行維護?

這是不可避免的 - 您的構建腳本必須隨您的解決方案一起發展。接受它作爲一個事實,並在您的估計中包含對構建腳本進行更改的時間。

此外,有沒有更好的開發解決方案,我可以建議,這將使整個過程不必要?

我不知道所有的要求,所以很難推薦非常具體的東西。我能說的建議是:

  • 您的解決方案創建一個共享構建腳本
  • 自動化手動任務,儘可能地(在合理範圍內)
  • 如果你正在努力實現自動化的東西 - 它可能是一個指示這需要重新思考的面積/重新設計
  • 確保你的隊友瞭解如何構建工程,並能夠進行更改自己 - 不要「自己」的構建,併成爲一個瓶頸

請記住,從沒有構建腳本到全自動化並不是一夜之間的過程。要有耐心,首先要關注引起最大疼痛的自動化區域。

如果我誤解了你的任何問題,請告訴我,我會更新答案。

+0

謝謝,阿諾德。清楚的是,配置設置被存儲在源代碼控制中,它們只是以不同的文件名存儲,因此需要上述過程。我想這允許開發人員從存儲庫中取出,而不必擔心他的特定配置會被覆蓋,迫使他用他的本地值重新編輯。似乎應該有更好的方法來做到這一點,例如也許可以導入本地文件來覆蓋web.config中的設置,就像MSBuild可以傳遞/p:TargetEnvPropsFile=xxx.proj來爲特定環境進行配置一樣。 –

+0

此外,我希望,就像我可以將解決方案文件傳遞給MSBuild(不需要編輯腳本來構建另一個項目,而只是將其添加到解決方案),我就能夠在腳本查找任何具有.template.config擴展名的文件,並將擴展名重命名爲.config。如果我不能這樣做,並且隨時添加一個新項目就需要編輯腳本,這樣我們就可以列出另一個要重命名的文件,那麼_almost_就會失去傳遞解決方案的目的,並且可能會爭執列出腳本中的每個項目都是單獨的。 –

+0

@MarcChu是的,你可以將這樣的邏輯添加到構建腳本中。我之前做過類似的事情(出於其他原因)。 –