web-dev-qa-db-fra.com

Copier un fichier dans le répertoire cible lors du déploiement à partir des services d'équipe Visual Studio

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? 

15
Georgy Grigoryev

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.

4
Pascal Berger

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:

  1. Ajoutez une étape "Copier les fichiers" pour copier "project.exe". Les paramètres sont les suivants:  enter image description here
  2. Ajoutez une étape "Copier les fichiers" pour copier le dossier "Certains scripts". Les paramètres sont les suivants:  enter image description here
  3. Ajoutez une étape "Copier et publier des artefacts de construction" pour copier ces fichiers dans un "dépôt". Les paramètres sont les suivants:  enter image description here

Maintenant, vous devriez obtenir les choses comme suivre dans le dossier de dépôt:

Project.exe
SomeScripts
    script.ps1
24
Eddie Chen - MSFT

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

7
igor_1024

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:

 TFS 2015 Build - Output to single folder step

2
DotBert

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

1
thomasgalliker

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.

 enter image description here

Cela aplatira la structure des dossiers et copiera tous les fichiers dans le fichier dossier cible spécifié.

0
PatrickLu-MSFT

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.

0