web-dev-qa-db-ja.com

Gitコマンドエラー処理を備えたPowershell-外部プログラムからのゼロ以外の終了コードで自動的に中止します

Gitを使用してWebアプリケーションをデプロイしています。そのため、Teamcityでアプリケーションを準備し(コンパイル、JSとHTMLの縮小、未使用のファイルの削除など)、Powershellのビルド手順を実行します。

$ErrorActionPreference = "Stop"
git init
git remote add Origin '%env.gitFolder%'
git fetch
git reset --mixed Origin/master
git add .
git commit -m '%build.number%'
git Push Origin master

ただし、例外がスローされた場合、スクリプトは続行され($ErrorActionPreference = "Stop"を設定しても)、ビルドは成功します。

エラーが発生し、ビルドが失敗したときにスクリプトを停止したい。

ビルドステップにFormat stderr output as: errorFail build if: an error message is logged by build runnerを入れようとしたので、ビルドは失敗しましたが、スクリプトは続行され、愚かなコミットが作成されます。

スクリプトにtry-catchを入れようとしましたが、catchに入力されません...

スクリプトを停止してビルドオンエラーに失敗した人はいますか?

英語でごめんなさい、私はフランス語です... ^^

10
Mickaël Doux

$ErrorActionPreference変数はnotの呼び出しに適用されます外部ユーティリティ([コンソール]アプリケーション)gitなど。

determine外部ユーティリティの成功と失敗の2つの方法

  • 自動$LASTEXITCODE変数を調べることにより、PowerShellは終了コード外部から報告ユーティリティ
    慣例により、値0successを示しますが、任意のnonzero値はfailureを示します。 (robocopy.exeなどの一部のユーティリティは、特定のゼロ以外の終了コードを使用して、エラー以外の状態も伝達することに注意してください。)

  • 報告されたSpecific終了コードに興味がない場合は、Boolean自動変数$?。これは、終了コード$Trueの場合は0を反映し、ゼロ以外の終了コードの場合は$Falseを反映します。

    • 警告:少なくともPowerShell [Core] 7.0.0-rc2まで、$?$falseand /の場合、$LASTEXITCODE0を誤って反映する可能性がありますstderrリダイレクト(2>または*>)が使用されますandコマンドがstderr出力を出力しました(それ自体は必ずしも失敗を示すわけではありません)- これを参照してくださいGitHubの問題

Acting失敗した場合は明示的アクションが必要です。通常はThrowキーワードを使用して、スクリプト終了エラーを生成します。


明らかに、すべての外部ユーティリティ呼び出しの後に$LASTEXITCODE/$?をチェックするのは面倒なので、このプロセスを容易にするラッパー関数を次に示します。

function Invoke-Utility {
<#
.SYNOPSIS
Invokes an external utility, ensuring successful execution.

.DESCRIPTION
Invokes an external utility (program) and, if the utility indicates failure by 
way of a nonzero exit code, throws a script-terminating error.

* Pass the command the way you would execute the command directly.
* Do NOT use & as the first argument if the executable name is not a literal.

.EXAMPLE
Invoke-Utility git Push

Executes `git Push` and throws a script-terminating error if the exit code
is nonzero.
#>
  $exe, $argsForExe = $Args
  $ErrorActionPreference = 'Continue' # to prevent 2> redirections from triggering a terminating error.
  try { & $exe $argsForExe } catch { Throw } # catch is triggered ONLY if $exe can't be found, never for errors reported by $exe itself
  if ($LASTEXITCODE) { Throw "$exe indicated failure (exit code $LASTEXITCODE; full command: $Args)." }
}

ここで、すべてのgit呼び出しの前にInvoke-Utility を追加する必要があり、それらのいずれかがゼロ以外の終了コードを報告した場合、スクリプトは中止されます。

それが冗長すぎる場合は、関数のエイリアスをSet-Alias iu Invoke-Utilityと定義します。この場合、iu を先頭に追加するだけで済みます。

iu git init
iu git remote add Origin '%env.gitFolder%'
iu git fetch
# ...
8
mklement0

ここでの問題は、gitによってスローされたエラーがPSによってトラップできないことだと思います。

図:

try {
    git Push
    Write-Host "I run after the git Push command"
}
catch {
    Write-Host "Something went wonky"
}

Note the missing <code>Write-Host</code> from the <code>catch</code> block!

catchブロックからWrite-Hostが欠落していることに注意してください。

ここで、gitコマンドの終了コードを確認する必要があります。

PowerShellで(私が知っている)最も簡単な方法は、$?の値を確認することです($?の詳細については、こちらをご覧ください: Powershellの `$?`とは何ですか?

try {
    git Push
    if (-not $?) {
        throw "Error with git Push!"
    }
    Write-Host "I run after the git Push command"
}
catch {
    Write-Host "Something went wonky"
    throw
}

Check our custom error (now caught by the <code>catch</code> block)!

カスタムエラーを確認してください(現在はcatchブロックでキャッチされています)。

7
gvee