web-dev-qa-db-ja.com

TeamCityPowerShellランナーでエラーを伝播させるにはどうすればよいですか

TeamCity 7ビルド構成があります。これは、さまざまなTeamCityパラメーターを使用した.ps1スクリプトの呼び出しにすぎません。

私はそれが設定の簡単な問題かもしれないことを望んでいました:

  • スクリプト

    ファイル

  • スクリプトファイル

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

  • スクリプト実行モード

    「-File」引数を指定して.ps1スクリプトを実行します

  • スクリプト引数

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

そして、私は期待します:

  • 引数を台無しにしてスクリプトが開始されない場合、ビルドは失敗します
  • script.ps1スクリプトがスローされると、ビルドが失敗します
  • スクリプトexitsが0以外のエラーレベルである場合、ビルドを失敗させたい(これは慣用的なPSエラー管理ではない可能性があります-.ps1は例外がない場合にのみ成功を報告する必要がありますか?)

質問:それはうまくいきません。それはどのように機能するはずですか?別のオプションを選択することで修正できる、大幅に間違っていることはありますか?

25
Ruben Bartelink

フレンドリーなTeamCityマニュアル に記載されているように:

エラーの設定Errorへの出力とビルド失敗条件の追加

構文エラーと例外が存在する場合、PowerShellはそれらをstderrに書き込みます。 TeamCityでビルドを失敗させるには、[エラー出力]オプションを[エラー]に設定し、エラー出力でビルドが失敗するビルド失敗条件を追加します。

これを機能させるための鍵は、twoのデフォルトを変更することです。

  1. ビルド障害条件の最上位で、スイッチをオンエラーメッセージはビルドランナーによってログに記録されます:
  2. [PowerShell]ビルドステップで、詳細オプションを表示してエラー出力を設定します:エラー

9.1では、次のように機能します(以前のバージョンでも機能しても驚かないでしょう)。

  1. デフォルトのオプションを使用してPowerShellビルドステップを作成する
  2. ドロップダウンを次のように変更しますスクリプト:ソースコード
  3. スクリプトの先頭にtrap { Write-Error "Exception $_" ; exit 98 }を追加します
  4. (TeamCityビルドスクリプト内に適した種類のスクリプト用のオプションですが、より正確なIMO)

    詳細オプションを表示してオンに切り替えますオプション:-NoProfile引数を追加します

  5. (オプションですが、私にとっては、これがより明確にレンダリングされるため、デフォルトである必要があります @ JamalMavadatによって提案されたように

    詳細オプションを表示してオンに切り替えますエラー出力:エラー

    (ASIDE @JetBrains:ラベルが「Formatstderr output as」の場合、誤解を招く可能性は低くなります)

これには、次の場合が含まれます。

  1. エラーを解析します[例外としてバブルアップし、すぐに実行を停止します]
  2. 例外[PSコードで直接または間接的にthrownが表示され、TCの終了コードがトリガーされてビルドが停止します]
  3. スクリプト内の明示的なexit nはビルドに伝播します(ゼロ以外の場合は失敗します)
33
Ruben Bartelink

TeamCityには 既知のバグ があり、元の投稿者が気付いた動作を引き起こします。

ただし、回避するのは簡単です。

PowerShellスクリプトの最後に、スクリプトの最後に到達したことを示す出力を追加します。

Echo "Packaging complete (end of script reached)"

次に、エコーしているテキストが出力に存在しない場合に失敗するように、ビルドに新しいビルド失敗条件を設定します。

8
Paul

あなたは物事を考えすぎています。これを試して:

  • 脚本

    File
    
  • スクリプトファイル

    Script.ps1
    

    これにパスを指定する必要はありません-デフォルトでは、チェックアウトディレクトリからの相対パスです。

  • スクリプト実行モード

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

これはまさに、Teamcity内で一連のPowerShellスクリプトを実行するために使用するものです。

更新

PowerShellスクリプトで失敗するとビルドが失敗するという、元の投稿のビットを見逃しました。お詫びします!

私は2つの異なる方法でパズルのその部分を解決しました。

通常のPowerShellスクリプトの場合

メインコードブロックをtry...catchでラップします。例外が発生した場合は、ゼロ以外の整数値を返します。正常に実行するには、0を返します。

成功のためにゼロを返すというこの規則は、歴史の中で非常に長い歴史があります-Unix/Linuxシステム、DOS、CP/Mなどで使用されています。

PSake ビルドスクリプトの場合

ラッパーのPowerShellスクリプトを使用してpsakeを呼び出し、チームシティビルドの結果を 応答メッセージの書き込み でstdoutに直接設定します。

スクリプトの開始時に、失敗を表すステータスメッセージを定義します。

$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はメッセージを受け取り、ビルドステータスを適切に設定します。

5
Bevan

TeamCity 9で私のために働く受け入れられた答えの代替(それはすべてのビルドステップに影響するので、「ビルド失敗条件」オプションを変更するのは好きではありません):-

PowerShellエラーでビルド手順を失敗させたかったのですが、かなりのメッセージが表示されました。だから私はエラーメッセージを投げてエラーコードを返したかったのです.... try/catch/finally救助に。

わかりやすくするために編集:このスクリプトは失敗するはずです。これは、例外をスローして終了コードを返すことが可能であることを示しています。つまり、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)
}
3
TinyRacoon

新しいTeamCityバージョンが手の届く範囲にある場合は、いくつかの PowerShellビルドランナー の改善点を確認する価値があります。

特に、Error Outputをデフォルトのwarningからerrorに変更すると興味があるかもしれません。

2
Jamal Mavadat

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 }"
2
Peter McEvoy

これは 9.xが提供するオプションに取って代わられました ですが、当時は間違いなく防弾であり、他に気に入ったソリューションが見つからなかったため、ここに残しておきます。


あなたはただうまくいく何かをすることができます。以下はでテストされています

  • スクリプトビットのエラー
  • 不足しているファイル
  • 0以外のERRORLEVELで終了するスクリプト

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} "</ code>

  • スクリプト実行モード

    「-Command-」引数を使用してスクリプトをPowerShellstdinに配置します

  • 追加のコマンドラインパラメータ

    -NoProfile

これが最善の答えではないことを願っています!

1
Ruben Bartelink

これは最後のエラーコードをチェックし、が0でない場合は終了します。

    If ($LASTEXITCODE -ne 0) {
        Write-Host "The result was of the previous script was " $LASTEXITCODE
        Exit $LASTEXITCODE
    }
0