练习 - 使用模板生成多个配置
你在上一个练习中实现了生成 Space Game 网站的管道。 你首先使用一个脚本执行各项生成操作,再将各项操作映射到相应的管道任务。 管道的输出是包含已编译的 Web 应用的一个 .zip 文件。
在本练习中,你将使用模板定义可生成项目文件中定义的任何配置的生成任务。 使用模板,定义一次逻辑即可供多次重用。 模板将多个 YAML 文件的内容合并到一个管道中。
提示
模块中的此步骤是可选的。 如果目前不想了解模板,请继续执行下一步:清理 Azure DevOps 环境。 有关模板的详细信息,请参阅模板类型和用法。
我们先来看看 Mara 和 Amita。
演示
Mara 非常高兴地共享她的结果,找到 Amita 向她展示生成管道。
Amita:你这么快就做好了,真是了不起! 其实我正打算去找你,因为我收到了一封电子邮件,告诉我生成已就绪。 谢谢! 但我发现管道只生成了“发布”配置。 我们还使用“调试”生成,以便在应用崩溃时捕获额外的信息。 可以添加这一个生成吗?
Mara:当然可以。 设置时,我忘了考虑“调试”生成。 我们一起来添加,可以吗?
Amita:你向我展示了定义生成步骤的 YAML 文件,但我不确定我是否知道如何对其进行修改。
Mara:没关系。 你可以在我键入的时候看着。 我们可以一起思考。
如何定义这两种生成配置?
请考虑以下任务,它们生成和发布 Space Game Web 项目的“发布”配置。 (不要将此代码添加到 azure-pipelines.yml 文件中。)
- task: DotNetCoreCLI@2
displayName: 'Build the project - Release'
inputs:
command: 'build'
arguments: '--no-restore --configuration Release'
projects: '**/*.csproj'
- task: DotNetCoreCLI@2
displayName: 'Publish the project - Release'
inputs:
command: 'publish'
projects: '**/*.csproj'
publishWebProjects: false
arguments: '--no-build --configuration Release --output $(Build.ArtifactStagingDirectory)/Release'
zipAfterPublish: true
要生成“调试”配置,可重复执行这两项任务,但需要将 Release
替换为 Debug
。
这样就能得到期望获得的结果,但是当生成变得更复杂或要求发生变化时会出现什么情况? 你需要手动定位和更改每个生成任务的两个变体。 添加额外的生成要求后,还需要创建两个任务,分别用于“调试”和“发布”这两个配置,以满足相应的要求。
更好的解决方案是使用模板。
什么是模板?
使用模板,定义一次常见的生成任务,即可多次重用这些任务。
从父管道调用模板,作为一个生成步骤。 可以将参数从父管道传递到模板中。
Mara 可定义将应用作为模板生成和发布的任务,再将该模板应用于她需要的每项配置。
定义模板
请记住,使用模板定义一次常见的生成任务,即可多次重用这些任务。 从父模板中调用模板作为一个生成步骤,并将参数从父管道传递到模板中。
你现在将创建一个模板,它可以生成项目文件中定义的任何配置。
从 Visual Studio Code 的集成控制台,在项目的根目录中创建“模板”目录。
mkdir templates
实际操作时,可以将模板文件放在任何位置。 无需将其放置在“模板”目录中。
在 Visual Studio Code 中,选择“文件”>“新建文件”。 接下来,选择“文件”>“保存”,在项目的“模板”目录中将空白文件保存为 build.yml。 例如 ~/mslearn-tailspin-spacegame-web/templates。
重要
如前所述,在 Windows 中,在“另存为类型”列表中选择“YAML”。
在 Visual Studio Code 中,将以下代码添加到 build.yml:
parameters: buildConfiguration: 'Release' steps: - task: DotNetCoreCLI@2 displayName: 'Build the project - ${{ parameters.buildConfiguration }}' inputs: command: 'build' arguments: '--no-restore --configuration ${{ parameters.buildConfiguration }}' projects: '**/*.csproj' - task: DotNetCoreCLI@2 displayName: 'Publish the project - ${{ parameters.buildConfiguration }}' inputs: command: 'publish' projects: '**/*.csproj' publishWebProjects: false arguments: '--no-build --configuration ${{ parameters.buildConfiguration }} --output $(Build.ArtifactStagingDirectory)/${{ parameters.buildConfiguration }}' zipAfterPublish: true
这些任务看起来像你之前定义的构建和发布应用程序的任务;但在模板中,处理输入参数的方式与处理普通变量不同。 有两个区别:
- 在模板文件中,使用
parameters
部分(而不是variables
)来定义输入。 - 在模板文件中,使用
${{ }}
语法(而不是$()
)来读取参数值。 读取参数的值时,将在其名称中包含parameters
部分。 例如${{ parameters.buildConfiguration }}
。
- 在模板文件中,使用
从管道调用模板
现在将调用刚才从管道生成的模板。 为“调试”配置执行一次此操作,然后为“发布”配置重复该过程。
在 Visual Studio Code 中,按如下所示修改 azure-pipelines.yml:
trigger: - '*' pool: vmImage: ubuntu-latest variables: buildConfiguration: 'Release' wwwrootDir: 'Tailspin.SpaceGame.Web/wwwroot' dotnetSdkVersion: '6.x' steps: - task: UseDotNet@2 displayName: 'Use .NET SDK $(dotnetSdkVersion)' inputs: version: '$(dotnetSdkVersion)' - task: Npm@1 displayName: 'Run npm install' inputs: verbose: false - script: './node_modules/.bin/node-sass $(wwwrootDir) --output $(wwwrootDir)' displayName: 'Compile Sass assets' - task: gulp@1 displayName: 'Run gulp tasks' - script: 'echo "$(Build.DefinitionName), $(Build.BuildId), $(Build.BuildNumber)" > buildinfo.txt' displayName: 'Write build info' workingDirectory: $(wwwrootDir) - task: DotNetCoreCLI@2 displayName: 'Restore project dependencies' inputs: command: 'restore' projects: '**/*.csproj' - template: templates/build.yml parameters: buildConfiguration: 'Debug' - template: templates/build.yml parameters: buildConfiguration: 'Release' - task: PublishBuildArtifacts@1 displayName: 'Publish Artifact: drop' condition: succeeded()
trigger: - '*' pool: name: 'Default' #replace if needed with name of your agent pool variables: buildConfiguration: 'Release' wwwrootDir: 'Tailspin.SpaceGame.Web/wwwroot' dotnetSdkVersion: '6.x' steps: - task: UseDotNet@2 displayName: 'Use .NET SDK $(dotnetSdkVersion)' inputs: version: '$(dotnetSdkVersion)' - task: Npm@1 displayName: 'Run npm install' inputs: verbose: false - script: './node_modules/.bin/node-sass $(wwwrootDir) --output $(wwwrootDir)' displayName: 'Compile Sass assets' - task: gulp@1 displayName: 'Run gulp tasks' - script: 'echo "$(Build.DefinitionName), $(Build.BuildId), $(Build.BuildNumber)" > buildinfo.txt' displayName: 'Write build info' workingDirectory: $(wwwrootDir) - task: DotNetCoreCLI@2 displayName: 'Restore project dependencies' inputs: command: 'restore' projects: '**/*.csproj' - template: templates/build.yml parameters: buildConfiguration: 'Debug' - template: templates/build.yml parameters: buildConfiguration: 'Release' - task: PublishBuildArtifacts@1 displayName: 'Publish Artifact: drop' condition: succeeded()
此文件与原始文件类似,只不过它会将生成和发布任务替换为对执行相同任务的模板的调用。
可以看到,为每个配置都调用了一次模板。 每个
template
任务都使用parameters
参数将配置名称传递给模板。
运行管道
现在,你需要将更改推送到 GitHub,并查看管道运行情况。
从集成终端,将 azure-pipelines.yml 和 templates/build.yml 添加到索引,提交更改,然后将更改推送到 GitHub。
git add azure-pipelines.yml templates/build.yml git commit -m "Support build configurations" git push origin build-pipeline
像之前那样,从 Azure Pipelines 中,跟踪生成的每个步骤。
管道运行时,你会看到该过程展开了模板中的任务。 生成和发布项目的任务会运行两次,也就是说,为每个生成配置执行一次。
生成完成后,返回到“摘要”页,然后像之前一样选择已发布的工件。 展开放置文件夹。
可以看到,管道为“调试”和“发布”配置分别生成了一个 .zip 文件。
将分支合并到主分支
此时,你有一个可用的生成管道,它可以完成 Mara 现在所需的一切操作。
在实际操作中,你将提交一个拉取请求,将 build-pipeline
分支合并到 main
分支中。
我们将暂时跳过该步骤。 在下一个模块中,你将了解在 GitHub 上与团队协作的一些方法,包括如何提交、评审和合并拉取请求。