AWSTemplateFormatVersion: "2010-09-09" Description: CI/CD pipeline — CodePipeline + CodeBuild for SAM deployments Parameters: GitHubOwner: Type: String Default: Sea-Haven-Industries GitHubRepo: Type: String Default: afterhours-shift-manager GitHubBranch: Type: String Default: main ConnectionArn: Type: String Description: CodeConnections ARN for GitHub StackName: Type: String Default: afterhours-shift-manager Description: Name of the SAM stack to deploy TemplateFile: Type: String Default: template.yaml SAMParameters: Type: String Default: "" Description: "CloudFormation parameter overrides (e.g. Key1=Value1 Key2=Value2)" Resources: ArtifactBucket: Type: AWS::S3::Bucket Properties: BucketName: !Sub "${StackName}-pipeline-artifacts" LifecycleConfiguration: Rules: - Id: expire-artifacts Status: Enabled ExpirationInDays: 30 Tags: - Key: Purpose Value: pipeline-artifacts - Key: ManagedBy Value: !Ref AWS::StackName CodeBuildRole: Type: AWS::IAM::Role Properties: RoleName: !Sub "${StackName}-codebuild" AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: codebuild.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: codebuild-permissions PolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents Resource: !Sub "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/${StackName}-build*" - Effect: Allow Action: - s3:GetObject - s3:PutObject - s3:GetBucketLocation Resource: - !GetAtt ArtifactBucket.Arn - !Sub "${ArtifactBucket.Arn}/*" CodeBuildProject: Type: AWS::CodeBuild::Project Properties: Name: !Sub "${StackName}-build" Description: !Sub "Build ${StackName} SAM application" ServiceRole: !GetAtt CodeBuildRole.Arn Artifacts: Type: CODEPIPELINE Environment: Type: ARM_CONTAINER ComputeType: BUILD_GENERAL1_SMALL Image: aws/codebuild/amazonlinux2-aarch64-standard:3.0 EnvironmentVariables: - Name: SAM_BUCKET Value: !Ref ArtifactBucket - Name: STACK_NAME Value: !Ref StackName - Name: TEMPLATE_FILE Value: !Ref TemplateFile - Name: SAM_PARAMETERS Value: !Ref SAMParameters Source: Type: CODEPIPELINE BuildSpec: buildspec.yml TimeoutInMinutes: 10 CloudFormationRole: Type: AWS::IAM::Role Properties: RoleName: !Sub "${StackName}-cfn-deploy" AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: cloudformation.amazonaws.com Action: sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/AWSLambda_FullAccess - arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess - arn:aws:iam::aws:policy/AmazonAPIGatewayAdministrator - arn:aws:iam::aws:policy/AmazonEventBridgeFullAccess - arn:aws:iam::aws:policy/IAMFullAccess - arn:aws:iam::aws:policy/AWSCloudFormationFullAccess Policies: - PolicyName: s3-kms-ssm PolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Action: - s3:GetObject - s3:GetBucketLocation Resource: - !GetAtt ArtifactBucket.Arn - !Sub "${ArtifactBucket.Arn}/*" - Effect: Allow Action: - ssm:GetParameter - ssm:GetParameters Resource: !Sub "arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/*" - Effect: Allow Action: - ses:SendEmail Resource: !Sub "arn:aws:ses:${AWS::Region}:${AWS::AccountId}:identity/*" PipelineRole: Type: AWS::IAM::Role Properties: RoleName: !Sub "${StackName}-pipeline" AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: codepipeline.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: pipeline-permissions PolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Action: - codeconnections:UseConnection Resource: !Ref ConnectionArn - Effect: Allow Action: - s3:GetObject - s3:PutObject - s3:GetBucketLocation Resource: - !GetAtt ArtifactBucket.Arn - !Sub "${ArtifactBucket.Arn}/*" - Effect: Allow Action: - codebuild:StartBuild - codebuild:BatchGetBuilds Resource: !GetAtt CodeBuildProject.Arn - Effect: Allow Action: - cloudformation:CreateStack - cloudformation:UpdateStack - cloudformation:DeleteStack - cloudformation:DescribeStacks - cloudformation:CreateChangeSet - cloudformation:DeleteChangeSet - cloudformation:DescribeChangeSet - cloudformation:ExecuteChangeSet - cloudformation:SetStackPolicy Resource: - !Sub "arn:aws:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/${StackName}/*" - Effect: Allow Action: - iam:PassRole Resource: !GetAtt CloudFormationRole.Arn Pipeline: Type: AWS::CodePipeline::Pipeline Properties: Name: !Sub "${StackName}-pipeline" RoleArn: !GetAtt PipelineRole.Arn ArtifactStore: Type: S3 Location: !Ref ArtifactBucket Stages: - Name: Source Actions: - Name: GitHub ActionTypeId: Category: Source Owner: AWS Provider: CodeStarSourceConnection Version: "1" Configuration: ConnectionArn: !Ref ConnectionArn FullRepositoryId: !Sub "${GitHubOwner}/${GitHubRepo}" BranchName: !Ref GitHubBranch DetectChanges: true OutputArtifacts: - Name: SourceOutput - Name: Build Actions: - Name: SAMBuild ActionTypeId: Category: Build Owner: AWS Provider: CodeBuild Version: "1" Configuration: ProjectName: !Ref CodeBuildProject InputArtifacts: - Name: SourceOutput OutputArtifacts: - Name: BuildOutput - Name: Deploy Actions: - Name: CreateChangeSet ActionTypeId: Category: Deploy Owner: AWS Provider: CloudFormation Version: "1" Configuration: ActionMode: CHANGE_SET_REPLACE StackName: !Ref StackName ChangeSetName: !Sub "${StackName}-changeset" TemplatePath: BuildOutput::packaged.yaml Capabilities: CAPABILITY_IAM,CAPABILITY_AUTO_EXPAND RoleArn: !GetAtt CloudFormationRole.Arn InputArtifacts: - Name: BuildOutput RunOrder: 1 - Name: ExecuteChangeSet ActionTypeId: Category: Deploy Owner: AWS Provider: CloudFormation Version: "1" Configuration: ActionMode: CHANGE_SET_EXECUTE StackName: !Ref StackName ChangeSetName: !Sub "${StackName}-changeset" RunOrder: 2 Outputs: PipelineName: Value: !Ref Pipeline PipelineUrl: Value: !Sub "https://${AWS::Region}.console.aws.amazon.com/codesuite/codepipeline/pipelines/${Pipeline}/view" ArtifactBucketName: Value: !Ref ArtifactBucket