SVN 倉庫增長至 10G+,自動構建速度急劇下降,微小提交需等待數小時。本文不介紹基礎搭建,專注優化實戰總結。
前兩點可優化,第三點屬硬性限制。
CCNET 透過 multi 型別 sourcecontrol 僅監控需編譯的專案路徑:
<sourcecontrol type="multi">
<sourceControls>
<svn>
<trunkUrl>https://xxx/projectA</trunkUrl>
<workingDirectory>x:\ccnet\svn\projectA</workingDirectory>
<username>name</username> <password>pwd</password>
<executable>x:\ccnet\Subversion\svn.exe</executable>
</svn>
<svn> ... projectB ... </svn>
<svn> ... projectC ... </svn>
</sourceControls>
</sourcecontrol>
效果:排除無需編譯的巨大非代碼目錄,更新速度質的飛躍。
需求:提交 FrameworkA 觸發 A/B/C 全編;提交 ProjectA 僅編 A。
方案:擴展 MSBuild 自定義 Task,讀取 CCNET 產生的 mods.xml 判斷變更專案,依預設依賴關係決定編譯目標。
<prebuild>
<modificationWriter>
<filename>mods.xml</filename>
<path>x:\ccnet\svn\build</path>
</modificationWriter>
</prebuild>
mods.xml 格式:
<Modification>
<Type>Modified</Type>
<FileName>xxx.cs</FileName>
<FolderName>/trunk/ProjectA/</FolderName>
<ModifiedTime>...</ModifiedTime>
<UserName>coderzh</UserName>
<ChangeNumber>8888</ChangeNumber>
<Comment>...</Comment>
</Modification>
<PropertyGroup>
<FrameworkAPath>\trunk\Framework</FrameworkAPath>
<ProjectAPath>\trunk\ProjectA</ProjectAPath> ...
</PropertyGroup>
<ItemGroup>
<SvnFolder Include="$(FrameworkAPath);"> <ProjectName>FrameworkA</ProjectName> </SvnFolder>
<SvnFolder Include="$(ProjectAPath);"> <ProjectName>ProjectA</ProjectName> </SvnFolder> ...
</ItemGroup>
<Target Name="FrameworkA">
<MSBuild Projects="$(FrameworkAPath)\FrameworkA.sln" Properties="Configuration=Release"/>
<CallTarget Targets="ProjectA;ProjectB;ProjectC" />
</Target>
<Target Name="ProjectA"> <MSBuild Projects="$(ProjectAPath)\ProjectA.sln" .../> </Target>
...
public class MyTask : Task {
[Output] public ITaskItem[] Targets { get; set; }
[Required] public ITaskItem[] Projects { get; set; }
[Required] public string SvnModifyFile { get; set; } // mods.xml
[Required] public string StateFile { get; set; } // CCNET state.xml
public override bool Execute() {
ReadLastBuildStatus(); // 讀取上次構建時間/結果
if (!lastBuildResult || lastBuildTime.Day != DateTime.Now.Day) {
SetAllTargetsToRun(); // 失敗或跨天 → 全量構建
} else {
SetTargetsToRunBySvnModify(); // 解析mods.xml決定增量目標
}
return true;
}
// 解析mods.xml獲取變更資料夾,匹配專案路徑,回傳Target清單
}
<UsingTask AssemblyFile="CoderZh.MyTask.dll" TaskName="MyTask"/>
<Target Name="Build">
<MyTask SvnModifyFile="$(SvnModifyFile)" StateFile="$(CCNetStateFile)" Projects="@(SvnFolder)">
<Output TaskParameter="Targets" ItemName="TargetNames"/>
</MyTask>
<Message Text="Targets to be call:@(TargetNames)"/>
<CallTarget Targets="@(TargetNames)"/>
</Target>
相關配置檔與代碼:mybuild.txt、ccnet.txt。出處:https://coderzh.cnblogs.com/