自动化软件构建过程是采用开发运营最佳实践的重要一步。为了帮助您实现目的,我们构建了 AWS CodeBuild,该服务是一项完全托管的持续集成服务,可编译源代码、运行测试并生成可供部署使用的程序包。
然而,客户的构建过程中可能存在很多自定义选项,我们已经看到有开发人员花费时间构建自己的自定义工作流程,以协调其软件构建所需的不同活动。例如,您可能会在需要部署快速修复时想要运行或不运行某些测试,或跳过代码的静态分析。 根据您的单元测试结果,您可能想要采取不同的错误,或通过 SNS 接收通知。
为了简化此过程,我们今天推出了全新的与 CodeBuild 的 AWS Step Functions 服务集成。现在,在执行状态机的过程中,您可以开始或停止构建、获取构建报告摘要并删除过去的构建执行记录。
用此方式,您可以定义自己的工作流程驱动型构建过程,并且手动或自动触发它。例如,您可以:
此次集成后,您可以使用 Step Functions 全部功能来自动执行您的软件构建。例如,您可以使用 Parallel
状态为版本的独立组件构建并行版本。您可以从代码库中所有的分支列表中使用 Map
状态为每个分支运行一组步骤(自动化构建、单元测试和集成测试)。 您还可以在同一个工作流程中利用其他 Step Functions 服务集成。 例如,您可以发送一条消息到 SQS 队列来跟踪您的活动,或者启动您刚使用 Amazon ECS 和 AWS Fargate 构建的容器化应用程序。
将 Step Functions 用于工作流程驱动型构建过程
我正在开发一个 Java Web 应用程序。为确保它在我添加新功能时正常运行,我使用 JUnit Jupiter 编写了几个测试。我希望这些测试在构建过程后运行,但希望它们不要一直运行,因为测试可能会减慢一些快速迭代的速度。当我运行测试时,我希望使用 CodeBuild 存储并查看我的测试报告。最后,我希望在测试运行及测试成功时通过 SNS 主题接收通知。
我在 CodeCommit 中创建了一个存储库,并且包含了 CodeBuild 的两个 buildspec 文件:
-
buildspec-notests.yml
仅执行构建,不执行测试。
为了设置 CodeBuild 项目和 Step Functions 状态机来自动执行构建,我使用了 AWS CloudFormation 与以下模板:
AWSTemplateFormatVersion: 2010-09-09
描述:用于获取 AWS CodeBuild 测试报告结果通知的 AWS Step Functions 示例项目
Resources:
CodeBuildStateMachine:
Type: AWS::StepFunctions::StateMachine
Properties:
RoleArn: !GetAtt [ CodeBuildExecutionRole, Arn ]
DefinitionString:
!Sub
- |-
{
"Comment": "An example of using CodeBuild to run (or not run) tests, get test results and send a notification.",
"StartAt": "Run Tests?",
"States": {
"Run Tests?": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.tests",
"BooleanEquals": false,
"Next": "Trigger CodeBuild Build Without Tests"
}
],
"Default": "Trigger CodeBuild Build With Tests"
},
"Trigger CodeBuild Build With Tests": {
"Type": "Task",
"Resource": "arn:${AWS::Partition}:states:::codebuild:startBuild.sync",
"Parameters": {
"ProjectName": "${projectName}"
},
"Next": "Get Test Results"
},
"Trigger CodeBuild Build Without Tests": {
"Type": "Task",
"Resource": "arn:${AWS::Partition}:states:::codebuild:startBuild.sync",
"Parameters": {
"ProjectName": "${projectName}",
"BuildspecOverride": "buildspec-notests.yml"
},
"Next": "Notify No Tests"
},
"Get Test Results": {
"Type": "Task",
"Resource": "arn:${AWS::Partition}:states:::codebuild:batchGetReports",
"Parameters": {
"ReportArns.$": "$.Build.ReportArns"
},
"Next": "All Tests Passed?"
},
"All Tests Passed?": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.Reports[0].Status",
"StringEquals": "SUCCEEDED",
"Next": "Notify Success"
}
],
"Default": "Notify Failure"
},
"Notify Success": {
"Type": "Task",
"Resource": "arn:${AWS::Partition}:states:::sns:publish",
"Parameters": {
"Message": "CodeBuild build tests succeeded",
"TopicArn": "${snsTopicArn}"
},
"End": true
},
"Notify Failure": {
"Type": "Task",
"Resource": "arn:${AWS::Partition}:states:::sns:publish",
"Parameters": {
"Message": "CodeBuild build tests failed",
"TopicArn": "${snsTopicArn}"
},
"End": true
},
"Notify No Tests": {
"Type": "Task",
"Resource": "arn:${AWS::Partition}:states:::sns:publish",
"Parameters": {
"Message": "CodeBuild build without tests",
"TopicArn": "${snsTopicArn}"
},
"End": true
}
}
}
- {snsTopicArn: !Ref SNSTopic, projectName: !Ref CodeBuildProject}
SNSTopic:
Type: AWS::SNS::Topic
CodeBuildProject:
Type: AWS::CodeBuild::Project
Properties:
ServiceRole: !Ref CodeBuildServiceRole
Artifacts:
Type: NO_ARTIFACTS
Environment:
Type: LINUX_CONTAINER
ComputeType: BUILD_GENERAL1_SMALL
Image: aws/codebuild/standard:2.0
Source:
Type: CODECOMMIT
Location: https://git-codecommit.us-east-1.amazonaws.com/v1/repos/binary-converter
CodeBuildExecutionRole:
Type: "AWS::IAM::Role"
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action: "sts:AssumeRole"
Principal:
Service: states.amazonaws.com
Path: "/"
Policies:
- PolicyName: CodeBuildExecutionRolePolicy
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- "sns:Publish"
Resource:
- !Ref SNSTopic
- Effect: Allow
Action:
- "codebuild:StartBuild"
- "codebuild:StopBuild"
- "codebuild:BatchGetBuilds"
- "codebuild:BatchGetReports"
Resource: "*"
- Effect: Allow
Action:
- "events:PutTargets"
- "events:PutRule"
- "events:DescribeRule"
Resource:
- !Sub "arn:${AWS::Partition}:events:${AWS::Region}:${AWS::AccountId}:rule/StepFunctionsGetEventForCodeBuildStartBuildRule"
CodeBuildServiceRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action: "sts:AssumeRole"
Effect: Allow
Principal:
Service: codebuild.amazonaws.com
Path: /
Policies:
- PolicyName: CodeBuildServiceRolePolicy
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- "logs:CreateLogGroup"
- "logs:CreateLogStream"
- "logs:PutLogEvents"
- "codebuild:CreateReportGroup"
- "codebuild:CreateReport"
- "codebuild:UpdateReport"
- "codebuild:BatchPutTestCases"
- "codecommit:GitPull"
Resource: "*"
Outputs:
StateMachineArn:
Value: !Ref CodeBuildStateMachine
ExecutionInput:
Description: Sample input to StartExecution.
Value:
>
{}
当 CloudFormation 堆栈创建后,状态机定义中有两个 CodeBuild 任务:
- 第一个是 CodeBuild 任务,它使用同步集成 (
startBuild.sync
) 自动等待构建终止后再进行下一步:
- 第二个是 CodeBuild 任务,它使用
BuildspecOverride
参数用未运行测试的文件覆盖构建所用的默认 buildspec 文件:
第一步是选择
查看状态机执行的输入,以决定是否运行测试。例如,要运行测试,我可以提供输入:
这一步是执行运行测试的可视化工作流程,所有测试均通过了。

我将 "tests"
的值更改为 false
,并开始在另一个分支上进行的新执行。

这一次,buildspec 没有执行测试,我收到没有运行测试的通知。
在 GitHub 或 CodeCommit 上的活动后自动开始此工作流程时,我可以查看特定模式的上一次提交消息,并相应自定义构建流程。例如,如果提交消息中包含 [skip tests]
字符串,我可以跳过测试。同样地,在生产环境中,如果提交中包含 [skip static analysis]
消息,我可以跳过代码静态分析,为紧急更改提供更快的集成。
扩展容器化应用程序的工作流程
将应用程序分配到不同环境的一种很好的做法是,将它们打包为 Docker 映像。用此方法,我还可以添加一个步骤到构建工作流程中,并在 Amazon ECS 任务(在 AWS Fargate 上运行)中为质量保证 (QA) 团队启动容器化应用程序。
首先,我在 ECR 中添加一个映像存储库,并为 CodeBuild 项目所用的服务角色添加上传到 ECR 的权限,如此处所述。
然后,在代码库中,我按照此示例添加:
-
Dockerfile
,以使用软件构建来准确 Docker 容器,并启动应用程序。
-
buildspec-docker.yml
文件,使用创建和上传 Docker 映像的命令。
最后一个工作流程是自动化以下所有步骤:
- 从源代码中构建软件。
- 创建 Docker 映像。
- 将 Docker 映像上传到 ECR。
- 在 ECS 和 Fargate 上开始 QA 环境。
- 发送一条表示 QA 环境已准备好的 SNS 通知。

工作流程及其步骤可以根据您的要求轻松自定义。例如,通过几项更改,您便可以调整 buildspec 文件,以将映像推送到 Docker Hub。
现已推出
CodeBuild 服务集成现已在提供 Step Functions 和 CodeBuild 服务的所有商业和 GovCloud 区域推出。有关区域可用性,请参阅 AWS 区域表。 有关更多信息,请查看文档。
正如 AWS 无服务器精英 Gojko Adzic 在 AWS 开发运营博客中提到的那样,CodeBuild 还可以用于执行管理任务。与 Step Functions 的集成开启了一系列新的可能性。
欢迎与我分享您打算将这项新服务集成用于何处!
– Danilo