Azure DevOps:如何将其他工件中的文件/文件夹纳入目标工件
解决Azure DevOps流水线跨项目文件包含问题
问题分析
你复制文件到$(Build.SourcesDirectory)后未被第二个项目的发布工件包含,核心原因是VSBuild默认仅打包项目文件(.csproj)中显式定义或默认包含的内容,复制到源码目录的文件不在项目的包含规则里,因此不会被纳入发布包。
以下是三种可行的解决方案:
方案一:修改第二个项目的.csproj文件(推荐,适配本地开发)
直接在第二个项目的.csproj中添加规则,指定要包含的目标文件夹内容,这样无论是本地构建还是流水线构建,都会自动包含这些文件。
在Second项目的.csproj中加入以下配置:
<ItemGroup> <!-- 匹配TargetFolder下的_folderToCopy目录及所有子内容 --> <Content Include="TargetFolder\_folderToCopy\**"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory> </Content> </ItemGroup>
流水线无需大幅调整,保留你原有的CopyFiles和VSBuild任务即可,复制到$(Build.SourcesDirectory)\second\TargetFolder\_folderToCopy的文件会被VSBuild自动打包进发布工件。
方案二:调整流水线流程,先构建再复制(无需修改项目文件)
先将第二个项目发布为文件夹而非zip包,复制文件到该发布文件夹后,再决定是否打包成zip并发布。
修改后的流水线YAML:
- task: DotNetCoreCLI@2 displayName: 'Build First project' inputs: command: 'publish' publishWebProjects: false projects: '**/First.sln' arguments: '--configuration $(BuildConfiguration) --output $(build.artifactstagingdirectory)\first' zipAfterPublish: false - task: PublishBuildArtifacts@1 inputs: PathtoPublish: '$(Build.ArtifactStagingDirectory)\first' ArtifactName: 'first' publishLocation: 'Container' # 构建第二个项目,输出为文件夹(不打包zip) - task: VSBuild@1 displayName: 'Build Second project' inputs: solution: '**\Second.sln' vsVersion: '17.0' msbuildArgs: '/p:DeployOnBuild=true /p:WebPublishMethod=FileSystem /p:SkipInvalidConfigurations=true /p:publishUrl="$(build.artifactstagingdirectory)\second"' platform: '$(buildPlatform)' configuration: '$(buildConfiguration)' # 将第一个项目的文件复制到第二个项目的发布目录 - task: CopyFiles@2 inputs: SourceFolder: '$(Build.ArtifactStagingDirectory)\first\wwwroot\_folderToCopy' Contents: '**' # 包含所有子文件和子文件夹 TargetFolder: '$(Build.ArtifactStagingDirectory)\second\TargetFolder\_folderToCopy' OverWrite: true # 可选:如果需要将发布目录打包为zip - task: ArchiveFiles@2 inputs: rootFolderOrFile: '$(Build.ArtifactStagingDirectory)\second' includeRootFolder: false archiveType: 'zip' archiveFile: '$(Build.ArtifactStagingDirectory)\second.zip' replaceExistingArchive: true # 发布工件(可选择发布文件夹或zip包) - task: PublishPipelineArtifact@1 inputs: targetPath: '$(Build.ArtifactStagingDirectory)\second' # 若用zip则改为$(Build.ArtifactStagingDirectory)\second.zip artifact: 'Second' publishLocation: 'pipeline'
方案三:直接向已生成的zip包添加文件(依赖外部工具)
如果不想调整构建流程,可借助7zip工具将文件直接添加到第二个项目生成的zip包中。
修改后的流水线YAML:
- task: DotNetCoreCLI@2 displayName: 'Build First project' inputs: command: 'publish' publishWebProjects: false projects: '**/First.sln' arguments: '--configuration $(BuildConfiguration) --output $(build.artifactstagingdirectory)\first' zipAfterPublish: false - task: PublishBuildArtifacts@1 inputs: PathtoPublish: '$(Build.ArtifactStagingDirectory)\first' ArtifactName: 'first' publishLocation: 'Container' # 构建第二个项目生成zip包 - task: VSBuild@1 displayName: 'Build Second project' inputs: solution: '**\Second.sln' vsVersion: '17.0' msbuildArgs: '/p:DeployOnBuild=true /p:WebPublishMethod=Package /p:PackageAsSingleFile=true /p:SkipInvalidConfigurations=true /p:PackageLocation="$(build.artifactstagingdirectory)\second"' platform: '$(buildPlatform)' configuration: '$(buildConfiguration)' # 安装7zip工具 - task: InstallTool@1 inputs: toolName: '7zip' toolVersion: '19.00' # 将目标文件添加到zip包(注意替换实际的zip文件名) - task: CmdLine@2 inputs: script: | # 假设VSBuild生成的zip名为Second.zip,需根据实际项目名称调整 7z a -tzip "$(Build.ArtifactStagingDirectory)\second\Second.zip" "$(Build.ArtifactStagingDirectory)\first\wwwroot\_folderToCopy\*" -r # -r参数表示包含子文件夹,若需排除特定文件可加-x!*.pdb之类的规则 # 发布包含新增文件的zip包 - task: PublishPipelineArtifact@1 inputs: targetPath: '$(Build.ArtifactStagingDirectory)\second' artifact: 'Second' publishLocation: 'pipeline'
关于“发布第二个项目时指定要包含的文件夹”的问题
可以通过两种方式实现:
- 项目文件层面:如方案一,在
.csproj中用<Content>节点指定要包含的文件夹,这是最规范的方式。 - 流水线参数层面:通过修改MSBuild参数,比如使用
/p:AdditionalFilesToPublish(部分项目类型支持),或者切换到FileSystem发布模式后手动复制文件(如方案二)。
内容的提问来源于stack exchange,提问作者Jakub Vojtašák
相关产品推荐
相关产品推荐

