从 visual studio 团队服务部署时复制目标目录中的一个文件
Copy one file in target directory on deploy from visual studio team services
我正在使用 VSTS 作为构建服务器,在构建时我想将 bin 文件夹内容复制到目标的根目录,并将自定义文件从另一个文件夹复制到该目标。 MSDN 建议我使用最小匹配模式,但它正在复制具有子目录结构的文件。我对恢复结构不感兴趣。
例如,我得到这个文件夹结构:
Project
MyProjectFiles
bin
x86 (it's build configuration)
Project.exe
Other project files
Project.sln
SomeScrips
script1.ps1
但是我想接收这个文件夹结构:
Project.exe
SomeScripts
script.ps1
我可以使用哪种最小匹配模式来满足我的要求?
使用基于 Web 的新构建系统,您可以在一个步骤中使用多个模式。因此你可以为你的情况做这样的事情:
Project\bin\x86\Release\project.exe
SomeScripts\**\*
或者如果您在变量中有构建平台和配置(例如 BuildPlatform
/ BuildConfiguration
),您也可以在构建步骤中使用它们,您可以在模式中使用它们:
Project\bin$(BuildPlatform)$(BuildConfiguration)\project.exe
SomeScripts\**\*
如果您希望 project.exe
位于根目录而不是结构中,您需要先使用 Copy Task
将文件暂存到所需的结构中。您可以使用 $(Build.StagingDirectory)
作为目标。之后使用 $(Build.StagingDirectory)
作为复制根的发布任务,并将从该根到 drop 的所有内容发布。
如果只复制没有文件夹结构的文件,需要指定复制根目录。由于 project.exe 与 script.ps1 文件位于不同的路径,因此您需要在不同的复制任务中复制它们。
按照以下步骤操作:
- 添加一个 "Copy Files" 步骤来复制 "project.exe"。设置如下:
- 添加 "Copy Files" 步骤以复制 "SomeScripts" 文件夹。设置如下:
- 添加 "Copy and Publish Build Artifacts" 步骤以将这些文件复制到 "drop"。设置如下:
现在你应该在 drop 文件夹中得到如下内容:
Project.exe
SomeScripts
script.ps1
对于那些想要在您的构建服务器中使用 PowerShell 脚本的人,这里有一个有效的(至少在我的构建服务器上;))示例:
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)
}
}
}
这是在 PowerShell 构建步骤中使用的脚本:
制作您要复制的每个文件的工件。然后为这些工件的每个文件创建一个 'copy file' 任务。然后它不复制源树结构。
"Flatten Folders" "Copy Files" 步骤的 "Advanced" 部分中的选项。
如果您正在使用 TFS 在线(Visual Studio 在线)并且不需要复制文件夹结构,请使用 "Copy Files" 步骤的 "Advanced" 部分中的 "Flatten Folders" 选项在您的构建定义中
使用 TFS2017update1 及更高版本 VSTS,您只需检查高级下的 Flatten Folders Copy Files Task 中的选项。目前最简单的解决方案。
This will flatten the folder structure and copy all files into the
specified target folder.
"flattenFolders" 选项也可用作 YAML 任务参数。以下代码摘录显示了一个 CopyFiles@2 任务,它将构建输出复制到 $(Build.ArtifactStagingDirectory)。当我指定选项 flattenFolders: true
时,嵌套文件夹结构 bin\release\...\My.exe
被展平,这意味着 exe 文件被复制到 $(Build.ArtifactStagingDirectory).
的根目录
- task: CopyFiles@2
displayName: 'Copy Files to: $(Build.ArtifactStagingDirectory)'
inputs:
SourceFolder: '$(system.defaultworkingdirectory)'
Contents: |
**\bin$(BuildConfiguration)\**\*.exe
TargetFolder: '$(Build.ArtifactStagingDirectory)'
flattenFolders: true
可以在此处找到有关 CopyFiles 任务的更多文档:
https://docs.microsoft.com/en-us/azure/devops/pipelines/tasks/utility/copy-files?view=vsts&tabs=yaml
我正在使用 VSTS 作为构建服务器,在构建时我想将 bin 文件夹内容复制到目标的根目录,并将自定义文件从另一个文件夹复制到该目标。 MSDN 建议我使用最小匹配模式,但它正在复制具有子目录结构的文件。我对恢复结构不感兴趣。
例如,我得到这个文件夹结构:
Project
MyProjectFiles
bin
x86 (it's build configuration)
Project.exe
Other project files
Project.sln
SomeScrips
script1.ps1
但是我想接收这个文件夹结构:
Project.exe
SomeScripts
script.ps1
我可以使用哪种最小匹配模式来满足我的要求?
使用基于 Web 的新构建系统,您可以在一个步骤中使用多个模式。因此你可以为你的情况做这样的事情:
Project\bin\x86\Release\project.exe
SomeScripts\**\*
或者如果您在变量中有构建平台和配置(例如 BuildPlatform
/ BuildConfiguration
),您也可以在构建步骤中使用它们,您可以在模式中使用它们:
Project\bin$(BuildPlatform)$(BuildConfiguration)\project.exe
SomeScripts\**\*
如果您希望 project.exe
位于根目录而不是结构中,您需要先使用 Copy Task
将文件暂存到所需的结构中。您可以使用 $(Build.StagingDirectory)
作为目标。之后使用 $(Build.StagingDirectory)
作为复制根的发布任务,并将从该根到 drop 的所有内容发布。
如果只复制没有文件夹结构的文件,需要指定复制根目录。由于 project.exe 与 script.ps1 文件位于不同的路径,因此您需要在不同的复制任务中复制它们。
按照以下步骤操作:
- 添加一个 "Copy Files" 步骤来复制 "project.exe"。设置如下:
- 添加 "Copy Files" 步骤以复制 "SomeScripts" 文件夹。设置如下:
- 添加 "Copy and Publish Build Artifacts" 步骤以将这些文件复制到 "drop"。设置如下:
现在你应该在 drop 文件夹中得到如下内容:
Project.exe
SomeScripts
script.ps1
对于那些想要在您的构建服务器中使用 PowerShell 脚本的人,这里有一个有效的(至少在我的构建服务器上;))示例:
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)
}
}
}
这是在 PowerShell 构建步骤中使用的脚本:
制作您要复制的每个文件的工件。然后为这些工件的每个文件创建一个 'copy file' 任务。然后它不复制源树结构。
"Flatten Folders" "Copy Files" 步骤的 "Advanced" 部分中的选项。
如果您正在使用 TFS 在线(Visual Studio 在线)并且不需要复制文件夹结构,请使用 "Copy Files" 步骤的 "Advanced" 部分中的 "Flatten Folders" 选项在您的构建定义中
使用 TFS2017update1 及更高版本 VSTS,您只需检查高级下的 Flatten Folders Copy Files Task 中的选项。目前最简单的解决方案。
This will flatten the folder structure and copy all files into the specified target folder.
"flattenFolders" 选项也可用作 YAML 任务参数。以下代码摘录显示了一个 CopyFiles@2 任务,它将构建输出复制到 $(Build.ArtifactStagingDirectory)。当我指定选项 flattenFolders: true
时,嵌套文件夹结构 bin\release\...\My.exe
被展平,这意味着 exe 文件被复制到 $(Build.ArtifactStagingDirectory).
- task: CopyFiles@2
displayName: 'Copy Files to: $(Build.ArtifactStagingDirectory)'
inputs:
SourceFolder: '$(system.defaultworkingdirectory)'
Contents: |
**\bin$(BuildConfiguration)\**\*.exe
TargetFolder: '$(Build.ArtifactStagingDirectory)'
flattenFolders: true
可以在此处找到有关 CopyFiles 任务的更多文档: https://docs.microsoft.com/en-us/azure/devops/pipelines/tasks/utility/copy-files?view=vsts&tabs=yaml