简体   繁体   English

由TeamCity触发的构建步骤始终构建 - 即使没有更改

[英]Build step triggered by TeamCity always builds - even when there are no changes

The problem: I am setting up TeamCity as a build server for an ASP.NET MVC project. 问题:我正在将TeamCity设置为ASP.NET MVC项目的构建服务器。 I am using Powershell with psake to run msbuild against our .csproj file and create a deployable package. 我正在使用Powershell和psake对我们的.csproj文件运行msbuild并创建一个可部署的包。 From the build server, I can open up powershell, run the script and, because there are no source code changes, msbuild does not regenerate the project DLL files. 从构建服务器,我可以打开powershell,运行脚本,因为没有源代码更改,msbuild不会重新生成项目DLL文件。 BUT, when I call the exact same script from the TeamCity web interface, msbuild ALWAYS rebuilds and regenerates the DLL files even though there are no changes. 但是,当我从TeamCity Web界面调用完全相同的脚本时,即使没有任何更改,msbuild也会重建并重新生成DLL文件。 Not what it should do AFAIK. 不是它应该做的AFAIK。

I have narrowed this problem down to a single step. 我把这个问题缩小到一步。 To keep it simple, I have set up my TeamCity config so it is not using any source control, it runs a single "powershell" build step that calls my powershell script. 为了简单起见,我设置了我的TeamCity配置,因此它没有使用任何源代码控制,它运行一个调用我的PowerShell脚本的“powershell”构建步骤。

The powershell script runs a single command: powershell脚本运行单个命令:

exec { &$msbuild $ProjectFile /t:Package "/p:PackageLocation=$PackageFile;OutDir=$TempPath;Configuration=$Config;SolutionDir=$BaseDir\Source\" /v:m }

When I call the script manually from a powershell command line, I see: 当我从powershell命令行手动调用脚本时,我看到:

CoreCompile:
Skipping target "CoreCompile" because all output files are up-to-date with respect to the input files.

When I call the exact same script through TeamCity, I see: 当我通过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".

Any ideas why running this script from TeamCity causes msbuild to detect changes and rebuild, but running the exact same script manually does not? 从TeamCity运行此脚本的任何想法都会导致msbuild检测到更改并重建,但是手动运行完全相同的脚本却没有?

UPDATE: Thinking this might be caused by some quirk with the TeamCity Powershell runner, I just tried making a batch file that passes the script into Powershell.exe and called it using the Command Line runner: 更新:认为这可能是由TeamCity Powershell运行器的一些怪癖造成的,我只是尝试制作一个批处理文件,将脚本传递到Powershell.exe并使用命令行运行程序调用它:

C:\WINDOWS\system32\WindowsPowerShell\v1.0\powershell.exe -NonInteractive -File D:\deploy\Build\run-build.ps1 && exit /b %ERRORLEVEL%

and I get the exact same behavior. 我得到了完全相同的行为。 If I call this batch file from the command line, the msbuild skips compilation. 如果我从命令行调用此批处理文件,则msbuild将跳过编译。 If I call it from TeamCity, the DLLs are recompiled. 如果我从TeamCity调用它,则会重新编译DLL。

UPDATE #2: Eureka! 更新#2:尤里卡! I turned on diagnostic debugging in msbuild and found the cause of the forced recompile. 我在msbuild中启用了诊断调试,并找到了强制重新编译的原因。 It is caused by the GenerateTargetFrameworkMonikerAttribute target. 它是由GenerateTargetFrameworkMonikerAttribute目标引起的。 Here is the key bits from the log output: 以下是日志输出中的关键位:

[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".

It looks like this target creates/updates an AssemblyAttributes file in the TEMP dir as specified in the TEMP environment variable. 看起来这个目标在TEMP环境变量中指定的TEMP目录中创建/更新AssemblyAttributes文件。 Apparently TeamCity overrides the TEMP environment variable and sets it to: C:\\TeamCity\\buildAgent\\temp\\buildTmp and this directory is cleaned before every build. 显然,TeamCity会覆盖TEMP环境变量并将其设置为: C:\\ TeamCity \\ buildAgent \\ temp \\ buildTmp,并在每次构建之前清除此目录。

I can see this if I call Get-ChildItem Env: from powershell: 如果我调用Get-ChildItem Env,我可以看到这个:来自powershell:

TEMP                           C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp
TMP                            C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp

But if I call it from the powershell script as called from TeamCity: 但是,如果我从来自TeamCity调用的powershell脚本中调用它:

TEMP                           C:\TeamCity\buildAgent\temp\buildTmp            
TMP                            C:\TeamCity\buildAgent\temp\buildTmp   

The key piece is that after this file is regnerated: 关键是在此文件被重新审核后:

[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".

And this is why the whole project is getting recompiled. 这就是整个项目重新编译的原因。

When I run the script from Powershell, the temp directory is not changed or cleaned and the build runs as expected. 当我从Powershell运行脚本时,不会更改或清除临时目录,并且构建按预期运行。

So, anyone know how I can either change the directory that this AssemblyAttributes file is created, or tell TeamCity to use a different TEMP dir? 那么,任何人都知道如何更改此AssemblyAttributes文件的创建目录,或者告诉TeamCity使用不同的TEMP目录? I have to believe that this is an issue that others have run into. 我不得不相信这是其他人遇到的问题。

Thanks! 谢谢!

So, as I mentioned in "Update #2" above, the problem seems to be caused by 2 things: - TeamCity sets the TEMP and TMP environment vars to its own temp directory - TeamCity "cleans" this temp directory prior to every build - Part of the msbuild process runs a GenerateTargetFrameworkMonikerAttribute target that updates a specific file in the directory specified by the TEMP environment variable - causing the compiler to thing it needs to recompile the whole project 因此,正如我在上面的“更新#2”中提到的,问题似乎是由两件事引起的: - TeamCity将TEMP和TMP环境变量设置为其自己的临时目录 - TeamCity在每次构建之前“清理”此临时目录 - msbuild进程的一部分运行GenerateTargetFrameworkMonikerAttribute目标,该目标更新TEMP环境变量指定的目录中的特定文件 - 导致编译器需要重新编译整个项目

Once I figured this out, I found an applicable answer in this unrelated question: In Visual Studio 2010 why is the .NETFramework,Version=v4.0.AssemblyAttributes.cpp file created, and can I disable this? 一旦我弄清楚这一点,我在这个无关的问题中找到了一个适用的答案: 在Visual Studio 2010中,为什么创建了.NETFramework,Version = v4.0.AssemblyAttributes.cpp文件,我可以禁用它吗?

So I added: 所以我补充说:

<Target Name="GenerateTargetFrameworkMonikerAttribute" />

to both of the projects in my solution that compile to DLLs and it worked. 在我的解决方案中编译为DLL的两个项目,它工作。

As a variation of obliojoe's answer, you can backup and restore these files to/from TEMP folder, if you do not want or cannot change the individual project files: 作为obliojoe答案的变体,如果您不想或不能更改单个项目文件,您可以将这些文件备份到TEMP文件夹或从TEMP文件夹恢复这些文件:

  1. First attempt to restore the files from a backup: 首次尝试从备份还原文件:

     copy temp\\*.* %%temp%% /y echo AssemblyAttributes restore attempted 
  2. Then perform your build step(s) using TeamCity build runner 然后使用TeamCity构建运行器执行构建步骤

  3. Backup the files: 备份文件:

     mkdir temp 2> nil copy %%temp%%\\*AssemblyAttributes.cs temp /y echo AssemblyAttributes files saved 

Both batch files need to run from the same directory. 两个批处理文件都需要从同一目录运行。

Do note the final ECHO in these batch files, it is there to guarantee successful exit (error code 0). 请注意这些批处理文件中的最终ECHO,它是为了保证成功退出(错误代码0)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 ReSharper“无法解析符号”,即使在项目构建时也是如此 - ReSharper "Cannot resolve symbol" even when project builds 尝试使用TeamCity构建asp.net mvc Web应用程序时出错 - Error when trying to build asp.net mvc web application with TeamCity 即使获取登录页面,returnUrl始终为null - returnUrl always null even when getting the login page 无法在TeamCity中构建.Net MVC项目 - Unable to build a .Net MVC project in TeamCity 当我事先不知道该对象时,如何构建一个生成MvcHtmlString Breadcrumb路径的递归函数? - How can I build a recursive function that builds an MvcHtmlString Breadcrumb trail when I don't know the object beforehand? MS Build步骤中的Nuget Restore - Nuget Restore in MS Build Step EndRequest-Context.Response.StatusCode始终为200(即使应为404) - EndRequest - Context.Response.StatusCode is always 200 (even when it should be 404) ASP.NET MVC即使没有人访问该网站,我也可以始终运行循环吗? - ASP.NET MVC Can I have a loop always be running even when no one visits the website? 即使数据不好,Ajax.BeginForm也会触发OnSuccess方法 - Ajax.BeginForm always fires OnSuccess method, even when data is bad WebApi分页不起作用,即使我正确设置了url参数,页面也始终为0 - WebApi Pagination not working, page is always 0 even when I set url parameter correctly
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM