in frontend-infrastructure/src/main/java/com/recognise/frontend/pipeline/FrontEndPipelineStack.java [48:260]
public FrontEndPipelineStack(Construct scope, String id, StackProps props) {
super(scope, id, props);
Topic topic = null;
if (!contextValue("approval_emails").isEmpty()) {
String[] approval_emails = contextValue("approval_emails").split(",");
topic = Topic.Builder.create(this, "ApprovalNotificationTopic")
.displayName("ApprovalNotificationTopic")
.topicName("ApprovalNotificationTopic")
.build();
for (String email : approval_emails) {
topic.addSubscription(EmailSubscription.Builder.create(email).build());
}
}
Bucket frontEndArtifactBucket = Bucket.Builder.create(this, "FrontEndArtifactBucket")
.versioned(true)
.build();
Trail frontEndTrail = Trail.Builder.create(this, "FrontEndCodeAwsCloudTrail")
.isMultiRegionTrail(true)
.trailName("FrontEndCodeAwsCloudTrail")
.managementEvents(ReadWriteType.WRITE_ONLY)
.includeGlobalServiceEvents(true)
.build();
String sourceZip = "frontend-source.zip";
frontEndTrail.addS3EventSelector(singletonList(S3EventSelector.builder()
.bucket(frontEndArtifactBucket)
.objectPrefix(sourceZip)
.build()));
Artifact sourceOutput = Artifact.artifact("FrontEndSourceOutput");
Artifact buildOutput = Artifact.artifact("FrontEndBuildOutput");
Artifact cdkBuildOutput = Artifact.artifact("FrontEndInfraOutput");
HashMap<String, BuildEnvironmentVariable> envVar = new HashMap<>();
envVar.put("SOURCE_OBJECT_KEY", BuildEnvironmentVariable.builder()
.value(sourceZip)
.build());
envVar.put("SOURCE_OUTPUT_BUCKET", BuildEnvironmentVariable.builder()
.value(frontEndArtifactBucket.getBucketName())
.build());
envVar.put("FOLDER_TO_INCLUDE", BuildEnvironmentVariable.builder()
.value("frontend frontend-infrastructure")
.build());
Project detectorBuild = Project.Builder.create(this, "DetectorFrontEndBuildProject")
.projectName("WebApplicationFrontEndPipelineDetector")
.description("Detects if frontend or frontend infra is updated. It will then invoke frontend pipeline")
.buildSpec(BuildSpec.fromSourceFilename("buildspec-copyartifact.yaml"))
.environment(BuildEnvironment.builder()
.computeType(LARGE)
.buildImage(AMAZON_LINUX_2_ARM)
.build())
.source(Source.gitHub(GitHubSourceProps.builder()
.cloneDepth(0)
.owner(contextValue("owner"))
.repo(contextValue("repo"))
.webhookFilters(asList(FilterGroup.inEventOf(EventAction.PUSH)
.andFilePathIs("frontend/"), FilterGroup.inEventOf(EventAction.PUSH)
.andFilePathIs("frontend-infrastructure/")))
.webhook(true)
.build()))
.environmentVariables(envVar)
.build();
detectorBuild.addToRolePolicy(PolicyStatement.Builder.create()
.effect(Effect.ALLOW)
.actions(asList(
"s3:PutObject",
"s3:GetObject",
"s3:GetObjectVersion"))
.resources(singletonList(frontEndArtifactBucket.getBucketArn() + "/*"))
.build());
detectorBuild.addToRolePolicy(PolicyStatement.Builder.create()
.effect(Effect.ALLOW)
.actions(singletonList(
"s3:ListBucket"))
.resources(singletonList(frontEndArtifactBucket.getBucketArn()))
.build());
PipelineProject codeBuildFrontEndProject = PipelineProject.Builder.create(this, "WebApplicationFrontEndBuild")
.projectName("WebApplicationFrontEndBuild")
.description("Builds frontend website")
.buildSpec(BuildSpec.fromSourceFilename(contextValue("frontend_build_spec")))
.environment(BuildEnvironment.builder()
.computeType(LARGE)
.buildImage(AMAZON_LINUX_2_ARM)
.build())
.build();
PipelineProject codeBuildFrontEndInfraProject = PipelineProject.Builder.create(this, "WebApplicationFrontEndInfrastructureBuild")
.projectName("WebApplicationFrontEndInfrastructureBuild")
.description("Builds frontend infrastructure")
.buildSpec(BuildSpec.fromSourceFilename(contextValue("frontend_infra_build_spec")))
.environment(BuildEnvironment.builder()
.computeType(LARGE)
.buildImage(AMAZON_LINUX_2_ARM)
.build())
.build();
Role adminRole = Role.Builder.create(this, "WebApplicationCodeBuildExecutionRole")
.assumedBy(ServicePrincipal.Builder.create("codebuild.amazonaws.com")
.build())
.managedPolicies(singletonList(ManagedPolicy.fromAwsManagedPolicyName("AdministratorAccess")))
.build();
PipelineProject codeBuildFrontEndInfraDeployProject = PipelineProject.Builder.create(this, "WebApplicationFrontEndInfrastructureDeploy")
.projectName("WebApplicationFrontEndInfrastructureDeploy")
.role(adminRole)
.description("Deploys frontend infrastructure and website")
.buildSpec(BuildSpec.fromSourceFilename(contextValue("frontend_infra_deploy_spec")))
.environment(BuildEnvironment.builder()
.computeType(LARGE)
.buildImage(AMAZON_LINUX_2_ARM)
.build())
.build();
codeBuildFrontEndInfraProject.addToRolePolicy(PolicyStatement.Builder.create()
.effect(Effect.ALLOW)
.actions(asList(
"cloudformation:DescribeStacks",
"cloudformation:GetTemplate"
)
)
.resources(singletonList("*"))
.build());
StageProps source = StageProps.builder()
.stageName("Source")
.actions(singletonList(
S3SourceAction.Builder.create()
.actionName("S3FrontEndSource")
.bucket(frontEndArtifactBucket)
.bucketKey(sourceZip)
.output(sourceOutput)
.trigger(S3Trigger.EVENTS)
.build()
)).build();
StageProps build = StageProps.builder()
.stageName("Build")
.actions(singletonList(
CodeBuildAction.Builder.create()
.actionName("FrontEndBuild")
.input(sourceOutput)
.type(BUILD)
.project(codeBuildFrontEndProject)
.outputs(singletonList(buildOutput))
.build()
)).build();
CodeBuildAction cdkAction = CodeBuildAction.Builder.create()
.actionName("FrontEndInfrastructureBuild")
.input(buildOutput)
.type(BUILD)
.project(codeBuildFrontEndInfraProject)
.outputs(singletonList(cdkBuildOutput))
.build();
StageProps infraBuild = StageProps.builder()
.stageName("InfraBuild")
.actions(singletonList(cdkAction))
.build();
List<IAction> approvalAndDeploy = new ArrayList<>();
if (null != topic) {
ManualApprovalAction approval = ManualApprovalAction.Builder.create()
.actionName("Approval")
.runOrder(1)
.additionalInformation("Approve before site is deployed for public.")
.notificationTopic(topic)
.build();
approvalAndDeploy.add(approval);
}
CodeBuildAction cdkDeployAction = CodeBuildAction.Builder.create()
.actionName("FrontEndInfrastructureBuild")
.runOrder(2)
.input(cdkBuildOutput)
.type(BUILD)
.project(codeBuildFrontEndInfraDeployProject)
.build();
approvalAndDeploy.add(cdkDeployAction);
StageProps approveAndDeploy = StageProps.builder()
.stageName("DeploySiteAndInfrastructure")
.actions(approvalAndDeploy)
.build();
Pipeline.Builder.create(this, "WebApplicationFrontendPipeline")
.pipelineName("WebApplicationFrontEndPipeline")
.artifactBucket(frontEndArtifactBucket)
.stages(asList(
source,
build,
infraBuild,
approveAndDeploy
)
).build();
}