Copy-Item ist defekt
tl;dr
Powershells Copy-Item -Path C:\parent\path\* -Recurse
in Verbindung mit der Azure DevOps Powershell Aufgabe hat einen fiesen Bug - Workaround siehe unten.
Der schwarze Powershell Schwan
Gestern bin ich in einen üblen Powershell Bug gelaufen, der in Verbindung mit der Powershell Task in Azure DevOps auftritt.
Die zehn Zeilen in der Powershell Aufgabe ersetzen ca. 20 einzelne, weniger flexible, Copy-Item Aufgaben.
Die Verwendung des Skripts ist vor allem auch deshalb notwendig, weil nicht bei jeder Ausführung des Releases, alle Kopier-Aufgaben ausgeführt werden müssen.
Die fehlerhafte Zeile folgt dem Muster
Copy-Item -Path C:\source\path\* -Recurse -Destination C:\target\path\ -Force
Dieser Befehlt kopiert normalerweise (außerhalb der DevOps Aufgabe) den gesamten Inhalt von path
in das Zielverzeichnis.
In der DevOps Aufgabe passiert das aber nicht, weil rekursiv ermittelte Verzeichnisse im Zielpfad nicht angelegt werden.
Der Fehler ist bekannt und sowohl im Azure Pipelines Repo als auch im Powershell Repo erfasst.
Da er im PS Repo seit 2018(!) offen ist, wird er wohl auch nicht mehr gefixt.
Workaround
Nachdem die Fehlerquelle gefunden war, konnte ich mit 5 Zeilen Code (alles unter dem Kommentar) einen simplen Fix fuer das Problem implementieren
$servicesToCopy = "komma,separierte,liste"
$servicesToCopy | ForEach-Object {
$source = "$(PackageDirectory)\$($_ -replace '\s','')\drop"
# Quellelemente einzeln holen da Copy-Item in Verbindung mit DevOps einen Bug hat,
# der die Verwendung von \* fuer den Verzeichnisinhalt unmoeglich macht
# s. https://github.com/PowerShell/PowerShell/issues/7005
$contentItems = gci $source
$contentItems | ForEach-Object {
Write-Host "Copy-Item -Path $($_.FullName) -Recurse -Destination $($destination) -Force -Verbose"
Copy-Item -Path $($_.FullName) -Recurse -Destination $($destination) -Force -Verbose
}
}
Dass in einer der grundlegendsten Funktionen wie Copy-Item
so ein Bug schlummert hätte ich wirklich nicht erwartet.
Hat aber zum Glück auch nur einen dreivirtel Tag gekostet, es zu finden und zu fixen.