28

我有一个 TeamCity 7 构建配置,它几乎只是.ps1使用各种 TeamCity 参数调用脚本。

我希望这可能是一个简单的设置问题:

  • 脚本

    文件

  • 脚本文件

    %system.teamcity.build.workingDir%/Script.ps1

  • 脚本执行模式

    使用“-File”参数执行 .ps1 脚本

  • 脚本参数

    %system.teamcity.build.workingDir% -OptionB %BuildConfigArgument% %BuildConfigArg2%

然后我会期望:

  • 如果我弄乱了我的论点并且脚本无法启动,则构建失败
  • 如果我的 Script.ps1 脚本抛出,则构建失败
  • 如果脚本exit具有非0错误级别,我希望构建失败(也许这不是惯用的 PS 错误管理 - .ps1 是否应该仅在没有异常的情况下报告成功?)

问题:它只是行不通。它应该如何工作?有没有我做错了什么可以通过选择不同的选项来解决?

4

10 回答 10

35

正如友好的 TeamCity 手册中所述

将错误输出设置为Error并添加构建失败条件

如果存在语法错误和异常,PowerShell 会将它们写入 stderr。要使 TeamCity 构建失败,请将错误输出选项设置为错误并添加一个构建失败条件,该条件将使构建在任何错误输出上失败。

完成这项工作的关键是更改两个默认值:

  1. Build Failure Conditions的顶层,构建运行器会记录打开错误消息:
  2. 在 [PowerShell] Build Step中,显示高级选项并设置错误输出:错误

在 9.1 中,以下工作(如果它也适用于早期版本,我不会感到惊讶):

  1. 使用默认选项创建 PowerShell 构建步骤
  2. 将下拉菜单更改为脚本:源代码
  3. trap { Write-Error "Exception $_" ; exit 98 }在脚本顶部添加一个
  4. (对于适合 TeamCity 构建脚本的脚本类型,可选但更正确的 IMO)

    显示高级选项并打开选项:添加 -NoProfile 参数

  5. (可选,但对我来说,这应该是默认设置,因为它按照@Jamal Mavadat 的建议呈现得更清晰)

    显示高级选项并打开错误输出:错误

    (除了@JetBrains:如果标签是“将标准错误输出格式化为”,那么误导性会降低)

这包括以下情况:

  1. 解析错误[冒泡为异常并立即停止执行]
  2. 异常 [ thrown 在您的 PS 代码中直接或间接显示并触发 TC 的退出代码以停止构建]
  3. 脚本中的显式exit n传播到构建(如果非零则失败)
于 2015-07-03T12:30:01.493 回答
8

TeamCity 中存在一个已知错误,导致原始发布者注意到的行为。

然而,这很容易解决。

在 PowerShell 脚本的末尾,添加指示已到达脚本末尾的输出:

Echo "Packaging complete (end of script reached)"

然后,在您的构建上设置一个新的构建失败条件,如果您回显的文本不存在于输出中,则该条件将失败。

于 2013-04-02T15:19:19.773 回答
5

你多虑了。试试这个:

  • 脚本

      File
    
  • 脚本文件

      Script.ps1
    

    你不需要给它一个路径——默认情况下,它是相对于结帐目录的。

  • 脚本执行模式

      Put script into PowerShell stdin with "-Command -" arguments
    

这正是我用来在 Teamcity 中运行一堆 powershell 脚本的方法。

更新

我错过了原始帖子中关于 powershell 脚本失败导致构建失败的内容。道歉!

我以两种不同的方式解决了这部分难题。

对于常规的 powershell 脚本

将主代码块包装在try...catch; 如果发生异常,则返回一个非零整数值。成功执行,返回 0。

这种为成功返回零的惯例可以追溯到很长一段历史——它被 Unix/Linux 系统、DOS、CP/M 等使用。

对于PSake构建脚本

使用包装器 powershell 脚本调用 psake 并通过将响应消息写入标准输出来直接设置 teamcity 构建的结果。

在脚本的开头,定义表示失败的状态消息:

$global:buildResult = "#teamcity[buildStatus status='FAILURE' text='It died.']

在 psake 脚本中,更新$global:buildResult以指示最后运行的专用任务成功。

$global:buildResult = "#teamcity[buildStatus status='SUCCESS' text='It lives.']

在包装脚本结束时,输出状态消息

write-host $global:buildResult

如果构建脚本中的任何内容失败,则最后一个任务将不会运行,并且将输出默认消息(指示失败)。

无论哪种方式,Teamcity 都会收到消息并适当地设置构建状态。

于 2012-08-24T03:55:50.827 回答
3

在 TeamCity 9 上对我有用的已接受答案的替代方案(我不喜欢更改“构建失败条件”选项,因为它会影响所有构建步骤):-

我希望 PowerShell 错误使构建步骤失败,但带有漂亮的消息。所以我想抛出一个错误消息并返回一个错误代码....尝试/捕获/最终救援。

为清楚起见进行编辑:此脚本应该失败。它表明可以抛出异常并返回退出代码。所以你得到了两个,TeamCity 处理的退出代码,在我的例子中,一个很好的清晰的调试消息,显示问题所在。

我的演示脚本:

Try {
    Write-Host "Demoing the finally bit"
    # Make sure if anything goes wrong in the script we get an exception
    $ErrorActionPreference = "Stop"

    # This will fail and throw an exception (unless you add the file)
    Get-Content IDontExist.txt
}
Catch
{
    # Throwing like this gives a pretty error message in the build log
    throw $_
    # These give less pretty/helpful error messages
    # Write-Host $_
    # Write-Host $_.Exception.Message
}
Finally
{
    # 69 because it's more funny than 1
    exit(69)
}
于 2015-09-04T10:43:28.413 回答
2

如果您可以使用较新的 TeamCity 版本,那么值得检查一些PowerShell 构建运行程序改进。

特别是,Error Output从默认更改warningerror您可能会感兴趣。

于 2014-12-15T04:53:12.840 回答
2

只需赞美您不需要与 Jenkins 一起工作的法律 .. 不能使用 PowerShell 步骤来解决类似问题。相反,我们需要使用一个“cmd”步骤来调用以下魔法包装器,该包装器将使异常和退出代码步骤失败:

%SystemRoot%\sysnative\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Bypass -NoLogo -NonInteractive -NoProfile -WindowStyle Hidden -Command "& { $ErrorActionPreference = 'Stop'; & 'path\to\script.ps1 -arg1 -arg2; EXIT $LASTEXITCODE }"
于 2015-07-03T12:50:21.677 回答
1

这已被9.x 提供的选项所取代,但我将把它留在这里,因为它当时绝对是防弹的,我找不到任何其他我更喜欢的解决方案。


你可以做一些有效的事情。以下内容已经过测试

  • 脚本位中的错误
  • 丢失文件
  • 脚本以非0ERRORLEVEL退出

在 TeamCity Powershell 运行器选项中,进行如下设置:

  • 脚本文件

    源代码

  • 脚本源

    $ErrorActionPreference='Stop'
    powershell -NoProfile "Invoke-Command -ScriptBlock { `$errorActionPreference='Stop'; %system.teamcity.build.workingDir%/Script.ps1 %system.teamcity.build.workingDir% --OptionB %BuildConfigArgument% %BuildConfigArg2%; exit `$LastExitCode }"

    (未包装版本:powershell -NoProfile "Invoke-Command -ScriptBlock { $errorActionPreference='Stop'; %system.teamcity.build.workingDir%/Script.ps1 %system.teamcity.build.workingDir% --OptionB %BuildConfigArgument% %BuildConfigArg2%; exit$LastExitCode }"

  • 脚本执行模式

    使用“-Command -”参数将脚本放入 PowerShell 标准输入

  • 附加命令行参数

    -NoProfile

我希望这不是最好的答案!

于 2012-07-25T10:44:43.380 回答
0

这将检查最后一个错误代码,如果不为 0,则退出。

    If ($LASTEXITCODE -ne 0) {
        Write-Host "The result was of the previous script was " $LASTEXITCODE
        Exit $LASTEXITCODE
    }
于 2019-02-19T09:56:12.590 回答
-1

Powershell v2 至少有一个 -File 选项会弄乱错误代码的问题。有一些关于它如何搞砸的细节。

答案是切换到 -Command 选项和/或用一个 bat 文件包装它,该文件检查 LastErrorCode 并在它应该失败时返回 1+。

http://zduck.com/2012/powershell-batch-files-exit-codes/

于 2014-03-24T11:48:29.737 回答
-1

使用这样的东西:

 echo "##teamcity[buildStatus status='FAILURE' text='Something went wrong while executing the script...']";

作为参考,请查看Teamcity的Reporting Build Status

于 2014-04-28T10:05:40.597 回答