J'utilise VSTS en tant que serveur de génération et lors de la construction, je veux copier le contenu du dossier bin à la racine de la cible, ainsi que les fichiers personnalisés d'un autre dossier vers cette cible. MSDN suggère d'utiliser un motif minimatch, mais qu'il copie des fichiers avec la structure de sous-répertoires. Je ne suis pas intéressé par la restauration de la structure.
Par exemple, je reçois cette structure de dossiers:
Project
MyProjectFiles
bin
x86 (it's build configuration)
Project.exe
Other project files
Project.sln
SomeScrips
script1.ps1
Mais je veux recevoir cette structure de dossier:
Project.exe
SomeScripts
script.ps1
Quel modèle de correspondance minimale puis-je utiliser pour mes besoins?
Avec le nouveau système de construction Web, vous pouvez utiliser plusieurs modèles en une seule étape. Par conséquent, vous pouvez faire quelque chose comme ceci pour votre cas:
Project\bin\x86\Release\project.exe
SomeScripts\**\*
Ou si vous avez la plate-forme de construction et la configuration dans une variable (par exemple, BuildPlatform
/BuildConfiguration
) que vous utilisez également dans l'étape de construction, vous pouvez les utiliser dans le modèle:
Project\bin\$(BuildPlatform)\$(BuildConfiguration)\project.exe
SomeScripts\**\*
Si vous voulez que le project.exe
soit à la racine au lieu de la structure, vous devez d'abord utiliser un Copy Task
pour placer vos fichiers dans la structure souhaitée. Vous pouvez utiliser $(Build.StagingDirectory)
comme cible pour cela. Ensuite, utilisez la tâche de publication avec $(Build.StagingDirectory)
en tant que racine de copie et publiez tout de cette racine à la liste.
Vous devez spécifier la racine de la copie si vous souhaitez copier des fichiers uniquement sans structure de dossiers. Puisque le fichier project.exe se trouve dans un chemin différent du fichier script.ps1, vous devez les copier dans une tâche de copie différente.
En suivant les étapes ci-dessous:
Maintenant, vous devriez obtenir les choses comme suivre dans le dossier de dépôt:
Project.exe
SomeScripts
script.ps1
Option "Aplatir les dossiers" de la section "Avancé" de l'étape "Copier les fichiers".
Si vous utilisez TFS Online (Visual Studio Online) et n'avez pas besoin de copier la structure de dossiers, utilisez l'option "Aplatir les dossiers" de la section "Avancé" de l'étape "Copier les fichiers" de votre définition de construction
Pour ceux qui souhaitent utiliser un script PowerShell dans votre serveur de génération, voici un exemple de travail (au moins sur mon serveur de génération;))
param
(
[string] $buildConfiguration = "Debug",
[string] $outputFolder = $PSScriptRoot + "\[BuildOutput]\"
)
Write-Output "Copying all build output to folder '$outputFolder'..."
$includeWildcards = @("*.dll","*.exe","*.pdb","*.sql")
$excludeWildcards = @("*.vshost.*")
# create target folder if not existing, or, delete all files if existing
if(-not (Test-Path -LiteralPath $outputFolder)) {
New-Item -ItemType Directory -Force -Path $outputFolder | Out-Null
# exit if target folder (still) does not exist
if(-not (Test-Path -LiteralPath $outputFolder)) {
Write-Error "Output folder '$outputFolder' could not be created."
Exit 1
}
} else {
Get-ChildItem -LiteralPath $outputFolder -Include * -Recurse -File | foreach {
$_.Delete()
}
Get-ChildItem -LiteralPath $outputFolder -Include * -Recurse -Directory | foreach {
$_.Delete()
}
}
# find all output files (only when in their own project directory)
$files = @(Get-ChildItem ".\" -Include $includeWildcards -Recurse -File |
Where-Object {(
$_.DirectoryName -inotmatch '\\obj\\' -and
$_.DirectoryName -inotmatch '\\*Test*\\' -and
$_.DirectoryName -ilike "*\" + $_.BaseName + "\*" -and
$_.DirectoryName -ilike "*\" + $buildConfiguration
)}
)
# copy output files (overwrite if destination already exists)
foreach ($file in $files) {
Write-Output ("Copying: " + $file.FullName)
Copy-Item $file.FullName $outputFolder -Force
# copy all dependencies from folder (also in subfolders) to output folder as well (if not existing already)
$dependencies = Get-ChildItem $file.DirectoryName -Include $includeWildcards -Exclude $excludeWildcards -Recurse -File
foreach ($dependency in $dependencies) {
$dependencyRelativePathAndFilename = $dependency.FullName.Replace($file.DirectoryName, "")
$destinationFileName = Join-Path -Path $outputFolder -ChildPath $dependencyRelativePathAndFilename
if (-not(Test-Path -LiteralPath $destinationFileName)) {
Write-Output ("Copying: " + $dependencyRelativePathAndFilename + " => " + $destinationFileName)
# create sub directory if not exists
$destinationDirectory = Split-Path $destinationFileName -Parent
if (-not(Test-Path -LiteralPath $destinationDirectory)) {
New-Item -Type Directory $destinationDirectory
}
Copy-Item $dependency.FullName $destinationDirectory
} else {
Write-Debug ("Ignoring (existing destination): " + $dependency.FullName)
}
}
}
Voici le script utilisé dans une étape de construction de PowerShell:
L'option "flattenFolders" est également disponible en tant que paramètre de tâche YAML. L'extrait de code suivant montre une tâche CopyFiles @ 2 qui copie le résultat de la construction dans le répertoire $ (Build.ArtifactStagingDirectory). Lorsque je spécifie l'option flattenFolders: true
, la structure de dossiers imbriquée bin\release\...\My.exe
est aplatie, signifie que les fichiers exe sont copiés à la racine de $ (Build.ArtifactStagingDirectory).
- task: CopyFiles@2
displayName: 'Copy Files to: $(Build.ArtifactStagingDirectory)'
inputs:
SourceFolder: '$(system.defaultworkingdirectory)'
Contents: |
**\bin\$(BuildConfiguration)\**\*.exe
TargetFolder: '$(Build.ArtifactStagingDirectory)'
flattenFolders: true
Une documentation supplémentaire concernant la tâche CopyFiles est disponible à l’adresse suivante: https://docs.Microsoft.com/en-us/Azure/devops/pipelines/tasks/utility/copy-files?view=vsts&tabs=yaml
Avec (TFS2017update1 et au-dessus, VSTS, vous pouvez simplement vérifier Aplatir les dossiers sous Options avancées dans Copier la tâche . La solution la plus simple pour le moment.
Cela aplatira la structure des dossiers et copiera tous les fichiers dans le fichier dossier cible spécifié.
Créez des artefacts de chaque fichier que vous souhaitez copier. Créez ensuite une tâche 'Copier le fichier' de chaque fichier de ces artefacts. Ensuite, il ne copie pas la structure de l'arbre source.