如何通过Azure DevOps YAML Pipeline部署6个控制台应用为WebJob
问题背景
我的场景
我有一个包含6个控制台应用的解决方案。
我的目标
将这6个控制台应用发布为同一App Service下的6个WebJob。
流程概述
6个控制台应用 → 转换 → 生成6个DLL并打包为单个ZIP文件 → 发布 → 部署到同一App Service下的6个WebJob。
问题
如何使用YAML实现上述流程?
现有Azure Pipeline YAML代码
trigger: - main variables: buildPlatform: 'Any CPU' buildConfiguration: 'Release' stages: - stage: Build displayName: 'Build stage' pool: vmImage: 'windows-latest' jobs: - job: BuildOrderShipmentJob displayName: 'Build Order Shipment Job' steps: - checkout: self displayName: 'checkout' - task: NuGetToolInstaller@0 displayName: "NuGet use 6.3.0" inputs: versionSpec: 6.3.0 - task: NuGetCommand@2 displayName: 'nuget restore' inputs: command: 'restore' restoreSolution: '**/*.sln' feedsToUse: 'select' - task: MSBuild@1 displayName: 'msbuild' inputs: solution: 'src/xxxxx/xxxxx.csproj' platform: '$(buildPlatform)' configuration: '$(buildConfiguration)' msbuildArguments: '/p:OutputPath=$(build.ArtifactStagingDirectory)/xxxxx-$(Build.BuildNumber)/App_Data/jobs/continuous/xxxxx' - task: ArchiveFiles@2 displayName: 'package' inputs: rootFolderOrFile: '$(build.ArtifactStagingDirectory)/xxxxx-$(Build.BuildNumber)' includeRootFolder: false archiveType: 'zip' archiveFile: '$(Build.ArtifactStagingDirectory)/xxxxx-$(Build.BuildNumber).zip' replaceExistingArchive: true - task: PublishBuildArtifacts@1 displayName: 'publish' inputs: PathtoPublish: '$(Build.ArtifactStagingDirectory)/xxxxx-$(Build.BuildNumber).zip' ArtifactName: 'drop' - stage: Test displayName: 'Test stage' pool: vmImage: 'windows-latest' jobs: - job: TestOrderShipmentJob displayName: 'Test Order Shipment Job' steps: - checkout: self displayName: 'checkout' - task: NuGetToolInstaller@0 displayName: "NuGet use 6.3.0" inputs: versionSpec: 6.3.0 - task: NuGetCommand@2 displayName: 'nuget restore' inputs: command: 'restore' restoreSolution: '**/*.sln' - task: VSBuild@1 displayName: 'vsbuild' inputs: solution: '**/*.sln' platform: '$(buildPlatform)' configuration: '$(buildConfiguration)' clean: true - task: DotNetCoreCLI@2 displayName: 'dotnet test' inputs: command: test arguments: '--collect:"XPlat Code Coverage" /p:CoverletOutputFormat=cobertura' publishTestResults: true workingDirectory: '$(System.DefaultWorkingDirectory)/src' - task: PublishCodeCoverageResults@1 displayName: 'publish code coverage results' inputs: codeCoverageTool: 'Cobertura' summaryFileLocation: '$(Agent.TempDirectory)/**/coverage.cobertura.xml' - stage: Deploy_Test displayName: 'Deploy test' dependsOn: Test condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) pool: name: 'bmersgtsteuw-app-eurotracs-pool' jobs: - deployment: BaukingOrderShipmentJob displayName: 'Deploy Order Shipment Job' environment: 'BME-CF-Test' strategy: runOnce: deploy: steps: - download: current artifact: drop - task: AzureRMWebAppDeployment@4 inputs: ConnectionType: AzureRM azureSubscription: 'ARM-Con-BME-SUB-TST-EUW-APP' appType: 'webApp' WebAppName: 'xxxapptsteuw-app-tst' package: '$(Pipeline.Workspace)/drop/xxxxx-$(Build.BuildNumber).zip' removeAdditionalFilesFlag: true - stage: Deploy_Prod displayName: 'Deploy production' dependsOn: Deploy_Test condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) pool: name: 'xxxrsgprdeuw-app-tst-pool' jobs: - deployment: YYYYYOrderShipmentJob displayName: 'Deploy Order Shipment Job' environment: XXXX-CF-Prod strategy: runOnce: deploy: steps: - download: current artifact: drop - task: AzureRMWebAppDeployment@4 inputs: ConnectionType: AzureRM azureSubscription: 'ARM-Con-XXXX-SUB-PRD-EUW-APP' appType: 'webApp' WebAppName: 'xxxappprdeuw-app-tst' package: '$(Pipeline.Workspace)/drop/xxxxx-$(Build.BuildNumber).zip' removeAdditionalFilesFlag: true
修改后的实现方案
trigger: - main variables: buildPlatform: 'Any CPU' buildConfiguration: 'Release' # 统一管理WebJob输出根路径 webJobsRootDir: '$(build.ArtifactStagingDirectory)/WebJobs-$(Build.BuildNumber)/App_Data/jobs/continuous' stages: - stage: Build displayName: '构建阶段' pool: vmImage: 'windows-latest' jobs: - job: BuildAllWebJobs displayName: '构建所有WebJob项目' steps: - checkout: self displayName: '拉取代码' - task: NuGetToolInstaller@0 displayName: "安装NuGet 6.3.0" inputs: versionSpec: 6.3.0 - task: NuGetCommand@2 displayName: 'NuGet还原依赖' inputs: command: 'restore' restoreSolution: '**/*.sln' feedsToUse: 'select' # 构建第一个WebJob,替换为实际项目路径 - task: MSBuild@1 displayName: '构建WebJob1' inputs: solution: 'src/WebJob1/WebJob1.csproj' platform: '$(buildPlatform)' configuration: '$(buildConfiguration)' msbuildArguments: '/p:OutputPath=$(webJobsRootDir)/WebJob1' # 构建第二个WebJob - task: MSBuild@1 displayName: '构建WebJob2' inputs: solution: 'src/WebJob2/WebJob2.csproj' platform: '$(buildPlatform)' configuration: '$(buildConfiguration)' msbuildArguments: '/p:OutputPath=$(webJobsRootDir)/WebJob2' # 重复添加剩余4个WebJob的构建任务,替换对应项目路径 - task: MSBuild@1 displayName: '构建WebJob3' inputs: solution: 'src/WebJob3/WebJob3.csproj' platform: '$(buildPlatform)' configuration: '$(buildConfiguration)' msbuildArguments: '/p:OutputPath=$(webJobsRootDir)/WebJob3' - task: MSBuild@1 displayName: '构建WebJob4' inputs: solution: 'src/WebJob4/WebJob4.csproj' platform: '$(buildPlatform)' configuration: '$(buildConfiguration)' msbuildArguments: '/p:OutputPath=$(webJobsRootDir)/WebJob4' - task: MSBuild@1 displayName: '构建WebJob5' inputs: solution: 'src/WebJob5/WebJob5.csproj' platform: '$(buildPlatform)' configuration: '$(buildConfiguration)' msbuildArguments: '/p:OutputPath=$(webJobsRootDir)/WebJob5' - task: MSBuild@1 displayName: '构建WebJob6' inputs: solution: 'src/WebJob6/WebJob6.csproj' platform: '$(buildPlatform)' configuration: '$(buildConfiguration)' msbuildArguments: '/p:OutputPath=$(webJobsRootDir)/WebJob6' # 打包所有WebJob为单个ZIP - task: ArchiveFiles@2 displayName: '打包所有WebJob' inputs: rootFolderOrFile: '$(build.ArtifactStagingDirectory)/WebJobs-$(Build.BuildNumber)' includeRootFolder: false archiveType: 'zip' archiveFile: '$(Build.ArtifactStagingDirectory)/AllWebJobs-$(Build.BuildNumber).zip' replaceExistingArchive: true - task: PublishBuildArtifacts@1 displayName: '发布构建产物' inputs: PathtoPublish: '$(Build.ArtifactStagingDirectory)/AllWebJobs-$(Build.BuildNumber).zip' ArtifactName: 'drop' - stage: Test displayName: '测试阶段' pool: vmImage: 'windows-latest' jobs: - job: TestAllProjects displayName: '测试所有项目' steps: - checkout: self displayName: '拉取代码' - task: NuGetToolInstaller@0 displayName: "安装NuGet 6.3.0" inputs: versionSpec: 6.3.0 - task: NuGetCommand@2 displayName: 'NuGet还原依赖' inputs: command: 'restore' restoreSolution: '**/*.sln' - task: VSBuild@1 displayName: '构建整个解决方案' inputs: solution: '**/*.sln' platform: '$(buildPlatform)' configuration: '$(buildConfiguration)' clean: true - task: DotNetCoreCLI@2 displayName: '运行单元测试' inputs: command: test arguments: '--collect:"XPlat Code Coverage" /p:CoverletOutputFormat=cobertura' publishTestResults: true workingDirectory: '$(System.DefaultWorkingDirectory)/src' - task: PublishCodeCoverageResults@1 displayName: '发布代码覆盖率报告' inputs: codeCoverageTool: 'Cobertura' summaryFileLocation: '$(Agent.TempDirectory)/**/coverage.cobertura.xml' - stage: Deploy_Test displayName: '部署到测试环境' dependsOn: Test condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) pool: name: 'bmersgtsteuw-app-eurotracs-pool' jobs: - deployment: DeployAllWebJobsToTest displayName: '部署所有WebJob到测试App Service' environment: 'BME-CF-Test' strategy: runOnce: deploy: steps: - download: current artifact: drop - task: AzureRMWebAppDeployment@4 inputs: ConnectionType: AzureRM azureSubscription: 'ARM-Con-BME-SUB-TST-EUW-APP' appType: 'webApp' WebAppName: 'xxxapptsteuw-app-tst' package: '$(Pipeline.Workspace)/drop/AllWebJobs-$(Build.BuildNumber).zip' removeAdditionalFilesFlag: true - stage: Deploy_Prod displayName: '部署到生产环境' dependsOn: Deploy_Test condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) pool: name: 'xxxrsgprdeuw-app-tst-pool' jobs: - deployment: DeployAllWebJobsToProd displayName: '部署所有WebJob到生产App Service' environment: XXXX-CF-Prod strategy: runOnce: deploy: steps: - download: current artifact: drop - task: AzureRMWebAppDeployment@4 inputs: ConnectionType: AzureRM azureSubscription: 'ARM-Con-XXXX-SUB-PRD-EUW-APP' appType: 'webApp' WebAppName: 'xxxappprdeuw-app-tst' package: '$(Pipeline.Workspace)/drop/AllWebJobs-$(Build.BuildNumber).zip' removeAdditionalFilesFlag: true
关键改动说明
- 统一路径管理:新增
webJobsRootDir变量,指定所有WebJob输出到App_Data/jobs/continuous/目录下的独立子文件夹(如果是触发型WebJob,需改为App_Data/jobs/triggered/)。 - 批量构建WebJob:为6个控制台应用分别添加MSBuild任务,将每个项目的输出直接写入对应WebJob的文件夹。
- 单ZIP打包:将包含所有WebJob结构的文件夹打包为一个ZIP,确保Azure App Service能识别所有WebJob。
- 统一部署:测试和生产环境只需部署这个单ZIP文件,即可将6个WebJob同时部署到同一App Service。
注意事项
- 替换YAML中
src/WebJob1/WebJob1.csproj等路径为实际项目路径。 - 根据WebJob类型调整
jobs/continuous为对应目录。 - 若要提升构建速度,可将多个MSBuild任务设置为并行执行。
内容的提问来源于stack exchange,提问作者Penguen
相关产品推荐
相关产品推荐

