尝试在 Azure DevOps 上进行 CI/CD
想做的事情 zuò de
因为想要试用Azure DevOps的持续集成/持续交付,所以尝试了一下,并记录下了试用过程。由于是试用性质较强,仅供参考!
管道内容
在管道中进行的是使用Terraform对Azure资源进行管理,其配置如下所示。
开发人员发布公关后,将触发公关用的流程,执行各种验证。然后,进行terraform plan并要求(手动)确认其内容。如果确认成功,公关流程就会成功并可进行合并。
合并后,将触发用于合并的流程,首先要求批准者批准发布,如果批准通过,则执行实际的terraform apply,这就是整个流程。
创建管道
在Azure DevOps上,有两种创建流水线的方式:经典流水线和YAML流水线。经典流水线是通过GUI进行创建,而YAML流水线则是通过YAML文件进行创建,正如其名称所示。
本次将使用其他 SCM 工具中使用的 YAML 文件进行 CI/CD 的创建。将参考以下文档进行创建。
在创建时,可以使用像VSCode这样的编辑器进行创建,但是在Azure DevOps上进行编辑,可以使用Intelligence功能,非常方便。
阶段、工作、步骤的关系
请注意,每个任务都由一个代理人执行。由于每个任务有不同的环境,因此在一个任务中安装的工具在另一个任务中无法使用。因此,需要对每个任务进行工具安装等操作。此外,基本上不能在一个任务中引用另一个任务创建的文件(如果将其视为工件可能可以实现?)。
连接到 Azure
连接到Azure需要几种方法,但本次我们将创建专用的服务主体并使用其认证信息。为了使权限范围最小化以适应用途,最好为每个存储库创建一个服务主体。
事先创建Azure到服务连接器,并从管道中调用其身份验证信息。
- task: AzureCLI@2
inputs:
azureSubscription: {YOUR_SERVICE_CONNECTION}
scriptType: 'bash'
scriptLocation: 'inlineScript'
inlineScript: |
az --version
az account show
addSpnToEnvironment: true
Terraform 扩展功能 (Terraform
使用Terraform时,可以选择自己编写脚本进行安装,但因为这样会比较麻烦,所以可以使用扩展功能。
点击「免费获取」并将其安装到存储库的组织上。
在使用时,根据以下方式调用任务并设置参数。
- task: TerraformTaskV4@4
displayName: terraform init
inputs:
provider: 'azurerm'
command: 'init'
workingDirectory: {WORKING_DIR}
backendServiceArm: {YOUR_SERVICE_CONNECTION}
backendAzureRmResourceGroupName: {YOUR_RESOURCE_GROUP}
backendAzureRmStorageAccountName: {YOUR_STORAGE_ACCOUNT}
backendAzureRmContainerName: {YOUR_CONATINER}
backendAzureRmKey: {YOUR_STATEFILE}
PR触发
这是最不容易理解的地方。
在 YMAL 模式中有触发器(trigger)和公共关系(pr),我最初打算使用它们,但似乎没有正常运作。经过仔细调查,发现需要在GUI设置中进行覆盖。
认可(验证)
当需要在某种发布时确认或需要批准内容时,可以使用手动验证和批准检查。
手动验证
通过使用手动验证任务,可以使后续流程能够暂停、再开始或拒绝确认。
认可检查
在 DevOps 上预先创建(定义)发布环境,并将该环境分配给 YAML 文件内的作业,以便在执行该作业之前需要获得批准。
PR 管道和合并管道
在 Azure DevOps 中,可以创建多个流水线,并可以将每个流水线的配置信息分别写入到不同的 YAML 文件中。
尽管可以在一个文件中触发这两个流水线,但这样会导致不易理解,所以选择将文件进行分割。
制作好的YAML文件
我创建了两个 YAML 文件,如下所示。说实话,管道的完成度不太好,只供参考!
pool:
vmImage: ubuntu-latest
# trigger 設定は Pull Request 時に CI を動作させるために、
# DevOps の GUI 設定で無効化している
# ファイルに残している理由:
# 1. trigger 設定を削除するとすべてのブランチへの Merge 時にトリガされてしまう
# 2. trigger: none にすると PR 時のトリガも動作しなくなってしまう
# https://zenn.dev/nuits_jp/articles/2023-07-02-azure-pipelines-pr-trigger
trigger:
- main
stages:
- stage: Validation
jobs:
- job: Format
steps:
- task: TerraformInstaller@0
displayName: install terraform
inputs:
terraformVersion: 'latest'
- script: |
cd infra/ && pwd
terraform fmt -check
if [ $? -ne 0 ]; then echo "You need to format"; exit 1; fi
displayName: terraform fmt
- job: Lint
steps:
- script: |
curl -s https://raw.githubusercontent.com/terraform-linters/tflint/master/install_linux.sh | bash
tflint --version
displayName: install tflint
- script: |
cd infra/ && pwd
tflint --init
tflint
displayName: tflint
- job: Validate
steps:
- task: TerraformInstaller@0
displayName: install terraform
inputs:
terraformVersion: 'latest'
- task: TerraformTaskV4@4
displayName: terraform init
inputs:
provider: 'azurerm'
command: 'init'
workingDirectory: {WORKING_DIR}
backendServiceArm: {YOUR_SERVICE_CONNECTION}
backendAzureRmResourceGroupName: {YOUR_RESOURCE_GROUP}
backendAzureRmStorageAccountName: {YOUR_STORAGE_ACCOUNT}
backendAzureRmContainerName: {YOUR_CONATINER}
backendAzureRmKey: {YOUR_STATEFILE}
- task: TerraformTaskV4@4
displayName: terraform validate
inputs:
provider: 'azurerm'
command: 'validate'
workingDirectory: {YOUR_WORKING_DIR}
- stage: Planning
jobs:
- job: Plan
steps:
- task: TerraformInstaller@0
displayName: install terraform
inputs:
terraformVersion: 'latest'
- task: TerraformTaskV4@4
displayName: terraform init
inputs:
provider: 'azurerm'
command: 'init'
workingDirectory: {WORKING_DIR}
backendServiceArm: {YOUR_SERVICE_CONNECTION}
backendAzureRmResourceGroupName: {YOUR_RESOURCE_GROUP}
backendAzureRmStorageAccountName: {YOUR_STORAGE_ACCOUNT}
backendAzureRmContainerName: {YOUR_CONATINER}
backendAzureRmKey: {YOUR_STATEFILE}
- task: TerraformTaskV4@4
displayName: terraform plan
inputs:
provider: 'azurerm'
command: 'plan'
workingDirectory: {YOUR_WORKING_DIR}
environmentServiceNameAzureRM: {YOUR_SERVICE_CONNECTION}
- stage: RequestManualValidation
jobs:
- job: ManualValidation
pool: server
steps:
- task: ManualValidation@0
displayName: check terraform plan
timeoutInMinutes: 1440 # task times out in 1 day
inputs:
notifyUsers: |
{USER_EMAIL}
instructions: 'Please validate the build configuration and resume'
onTimeout: 'reject'
pool:
vmImage: ubuntu-latest
trigger:
branches:
include:
- main
paths:
include:
- {TARGET_PATH}
stages:
- stage: Provisioning
jobs:
- deployment: Apply
environment: Check Terraform Plan
strategy:
runOnce:
deploy:
steps:
- checkout: self
- task: TerraformInstaller@0
displayName: install terraform
inputs:
terraformVersion: 'latest'
- task: TerraformTaskV4@4
displayName: terraform init
inputs:
provider: 'azurerm'
command: 'init'
workingDirectory: {WORKING_DIR}
backendServiceArm: {YOUR_SERVICE_CONNECTION}
backendAzureRmResourceGroupName: {YOUR_RESOURCE_GROUP}
backendAzureRmStorageAccountName: {YOUR_STORAGE_ACCOUNT}
backendAzureRmContainerName: {YOUR_CONATINER}
backendAzureRmKey: {YOUR_STATEFILE}
- task: TerraformTaskV4@4
displayName: terraform apply
inputs:
provider: 'azurerm'
command: 'apply'
workingDirectory: {WORKING_DIR}
environmentServiceNameAzureRM: {YOUR_SERVICE_CONNECTION}
以上就是。