問題: TeamCityをASP.NETMVCプロジェクトのビルドサーバーとして設定しています。Powershellとpsakeを使用して、.csprojファイルに対してmsbuildを実行し、デプロイ可能なパッケージを作成しています。ビルドサーバーから、PowerShellを開いてスクリプトを実行できます。ソースコードが変更されていないため、msbuildはプロジェクトDLLファイルを再生成しません。ただし、TeamCity Webインターフェイスからまったく同じスクリプトを呼び出すと、変更がない場合でも、msbuildは常にDLLファイルを再構築して再生成します。それがAFAIKをすべきではありません。
この問題を1つのステップに絞り込みました。簡単にするために、ソース管理を使用しないようにTeamCity構成を設定しました。これにより、PowerShellスクリプトを呼び出す単一の「PowerShell」ビルドステップが実行されます。
PowerShellスクリプトは、次の1つのコマンドを実行します。
exec { &$msbuild $ProjectFile /t:Package "/p:PackageLocation=$PackageFile;OutDir=$TempPath;Configuration=$Config;SolutionDir=$BaseDir\Source\" /v:m }
PowerShellコマンドラインからスクリプトを手動で呼び出すと、次のように表示されます。
CoreCompile:
Skipping target "CoreCompile" because all output files are up-to-date with respect to the input files.
TeamCityを介してまったく同じスクリプトを呼び出すと、次のように表示されます。
[11:11:26]: CoreCompile:
[11:11:26]: c:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\Csc.exe /noconfig ...
<SNIP>
[11:11:32]: CopyFilesToOutputDirectory:
[11:11:32]: Copying file from "obj\Demo\Website.Web.dll" to "d:\deploy\Build\package\Demo\temp\Website.Web.dll".
[11:11:32]: Website.Web -> d:\deploy\Build\package\Demo\temp\Website.Web.dll
[11:11:32]: Copying file from "obj\Demo\Website.Web.pdb" to "d:\deploy\Build\package\Demo\temp\Website.Web.pdb".
[11:11:32]: _CopyWebApplicationLegacy:
[11:11:32]: Copying Web Application Project Files for Website.Web
[11:11:32]: Copying file from "obj\Demo\Website.Web.dll" to "d:\deploy\Build\package\Demo\temp\_PublishedWebsites\Website.Web\bin\Website.Web.dll".
[11:11:32]: Copying file from "obj\Demo\Website.Web.pdb" to "d:\deploy\Build\package\Demo\temp\_PublishedWebsites\Website.Web\bin\Website.Web.pdb".
[11:11:32]: Copying file from "d:\deploy\Build\package\Demo\temp\Website.Data.dll" to "d:\deploy\Build\package\Demo\temp\_PublishedWebsites\Website.Web\bin\Website.Data.dll".
[11:11:32]: Copying file from "d:\deploy\Build\package\Demo\temp\Website.Data.pdb" to "d:\deploy\Build\package\Demo\temp\_PublishedWebsites\Website.Web\bin\Website.Data.pdb".
TeamCityからこのスクリプトを実行すると、msbuildが変更を検出して再構築するのに、まったく同じスクリプトを手動で実行しない理由はありますか?
更新: これは、TeamCity Powershellランナーの癖が原因である可能性があると考えて、スクリプトをPowershell.exeに渡し、コマンドラインランナーを使用して呼び出すバッチファイルを作成してみました。
C:\WINDOWS\system32\WindowsPowerShell\v1.0\powershell.exe -NonInteractive -File D:\deploy\Build\run-build.ps1 && exit /b %ERRORLEVEL%
まったく同じ動作になります。コマンドラインからこのバッチファイルを呼び出すと、msbuildはコンパイルをスキップします。TeamCityから呼び出すと、DLLが再コンパイルされます。
更新#2: ユーレカ!msbuildで診断デバッグをオンにして、強制的な再コンパイルの原因を見つけました。これは、GenerateTargetFrameworkMonikerAttributeターゲットが原因で発生します。ログ出力のキービットは次のとおりです。
[15:23:28]: Target "GenerateTargetFrameworkMonikerAttribute" in file "c:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets" from project "d:\deploy\source\Website.Data\Website.Data.csproj" (target "BeforeCompile" depends on it):
[15:23:28]: Building target "GenerateTargetFrameworkMonikerAttribute" completely.
[15:23:28]: Output file "C:\TeamCity\buildAgent\temp\buildTmp\.NETFramework,Version=v4.0.AssemblyAttributes.cs" does not exist.
[15:23:28]: Using "WriteLinesToFile" task from assembly "Microsoft.Build.Tasks.v4.0, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a".
[15:23:28]: Task "WriteLinesToFile"
[15:23:28]: Done executing task "WriteLinesToFile".
[15:23:28]: Done building target "GenerateTargetFrameworkMonikerAttribute" in project "SMM.Data.csproj".
このターゲットは、TEMP環境変数で指定されているように、TEMPディレクトリにAssemblyAttributesファイルを作成/更新しているようです。どうやらTeamCityはTEMP環境変数をオーバーライドし、それをC:\ TeamCity \ buildAgent \ temp \ buildTmpに設定し、このディレクトリはすべてのビルドの前にクリーンアップされるようです。
これは、PowershellからGet-ChildItem Env:を呼び出すとわかります。
TEMP C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp
TMP C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp
しかし、TeamCityから呼び出されたPowerShellスクリプトから呼び出すと、次のようになります。
TEMP C:\TeamCity\buildAgent\temp\buildTmp
TMP C:\TeamCity\buildAgent\temp\buildTmp
重要な点は、このファイルが認識された後、次のことです。
[15:23:28]: Building target "CoreCompile" completely.
[15:23:28]: Input file "C:\TeamCity\buildAgent\temp\buildTmp\.NETFramework,Version=v4.0.AssemblyAttributes.cs" is newer than output file "obj\Demo\SMM.Data.pdb".
そして、これがプロジェクト全体が再コンパイルされる理由です。
Powershellからスクリプトを実行すると、一時ディレクトリが変更またはクリーンアップされず、ビルドが期待どおりに実行されます。
したがって、このAssemblyAttributesファイルが作成されるディレクトリを変更する方法、またはTeamCityに別のTEMPディレクトリを使用するように指示する方法を知っている人はいますか?これは他の人が遭遇した問題だと私は信じなければなりません。
ありがとう!