internal CdkPipelineStack(Construct scope, string id, CdkPipelineStackProps props = null) : base(scope, id, props) { var sourceArtifact = new Artifact_("SourceArtifact"); var outputArtifact = new Artifact_("OutputArtifact"); var sourceAction = new CodeCommitSourceAction(new CodeCommitSourceActionProps { ActionName = "CodeCommit", Output = sourceArtifact, Repository = props.MyRepository, Branch = "main", }); // Self mutation var pipeline = new CdkPipeline(this, "CdkPipeline", new CdkPipelineProps { PipelineName = "CrossAccountSourcePipeline", CloudAssemblyArtifact = outputArtifact, SourceAction = sourceAction, // It synthesizes CDK code to cdk.out directory which is picked by SelfMutate stage to mutate the pipeline SynthAction = new SimpleSynthAction(new SimpleSynthActionProps { SourceArtifact = sourceArtifact, CloudAssemblyArtifact = outputArtifact, InstallCommands = new[] { "npm install -g aws-cdk", }, BuildCommands = new[] { "dotnet build" }, SynthCommand = "cdk synth", }), }); }
public WorkshopPipelineStack(Constructs.Construct scope = null, string id = null, IStackProps props = null) : base(scope, id, props) { var repo = new Repository(this, "WorkshopRepo", new RepositoryProps { RepositoryName = "WorkshopRepo" }); var sourceArtifact = new Artifact_(); var cloudAssemblyArtifact = new Artifact_(); var pipeline = new CdkPipeline(this, "Pipeline", new CdkPipelineProps { PipelineName = "WorkshopPipeline", CloudAssemblyArtifact = cloudAssemblyArtifact, SourceAction = new CodeCommitSourceAction(new CodeCommitSourceActionProps { ActionName = "CodeCommit", Output = sourceArtifact, Repository = repo }), SynthAction = SimpleSynthAction.StandardNpmSynth(new StandardNpmSynthOptions { SourceArtifact = sourceArtifact, CloudAssemblyArtifact = cloudAssemblyArtifact, InstallCommand = "npm install -g aws-cdk" + " && wget -q https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb" + " && dpkg -i packages-microsoft-prod.deb" + " && apt-get update" + " && apt-get install -y dotnet-sdk-3.1", BuildCommand = "dotnet build src" }) }); var deploy = new WorkshopPipelineStage(this, "Deploy"); var deployStage = pipeline.AddApplicationStage(deploy); }
public PipelineStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) { var sourceArtifact = new Artifact_(); var cloudAssemblyArtifact = new Artifact_(); var pipeline = new CdkPipeline(this, "CdkPipeline", new CdkPipelineProps { PipelineName = "sandbank-api-pipeline", CdkCliVersion = "1.63.0", SourceAction = new GitHubSourceAction(new GitHubSourceActionProps { ActionName = "synth-cdk", Owner = "nicostouch", Repo = "sandbank", Output = sourceArtifact, OauthToken = SecretValue.SecretsManager("github/oauth/token") }), SynthAction = new SimpleSynthAction(new SimpleSynthActionProps { SynthCommand = "cdk synth", Subdirectory = "DevOps/Infrastructure/CDK", SourceArtifact = sourceArtifact, CloudAssemblyArtifact = cloudAssemblyArtifact }), CloudAssemblyArtifact = cloudAssemblyArtifact }); }
internal PipelineStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) { Artifact_ sourceArtifact = new Artifact_(); Artifact_ cloudAssemblyArtifact = new Artifact_(); CdkPipeline pipeline = new CdkPipeline(this, "LambdaApiSolutionPipeline", new CdkPipelineProps() { CloudAssemblyArtifact = cloudAssemblyArtifact, PipelineName = "LambdaApiSolutionPipeline", SourceAction = new GitHubSourceAction(new GitHubSourceActionProps() { ActionName = "GitHubSource", Output = sourceArtifact, OauthToken = SecretValue.SecretsManager(Constants.GitHubTokenSecretsManagerId), Owner = Constants.Owner, Repo = Constants.RepositoryName, Branch = Constants.Branch, Trigger = GitHubTrigger.POLL }), SynthAction = new SimpleSynthAction(new SimpleSynthActionProps() { Environment = new BuildEnvironment { // required for .NET 5 // https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-available.html BuildImage = LinuxBuildImage.STANDARD_5_0 }, SourceArtifact = sourceArtifact, CloudAssemblyArtifact = cloudAssemblyArtifact, Subdirectory = "LambdaApiSolution", InstallCommands = new[] { "npm install -g aws-cdk" }, BuildCommands = new[] { "dotnet build src/LambdaApiSolution.sln" }, SynthCommand = "cdk synth" }) }); CdkStage developmentStage = pipeline.AddApplicationStage(new SolutionStage(this, "Development")); CdkStage testStage = pipeline.AddApplicationStage(new SolutionStage(this, "Test")); testStage.AddManualApprovalAction(new AddManualApprovalOptions() { ActionName = "PromoteToProduction" }); CdkStage productionStage = pipeline.AddApplicationStage(new SolutionStage(this, "Production")); }
internal PipelineStack(Construct scope, string id, Configuration configuration, IStackProps props = null) : base(scope, id, props) { var repository = Repository.FromRepositoryArn(this, "Repository", configuration.Source.RepositoryArn); var sourceArtifact = new Artifact_(); var outputArtifact = new Artifact_(); var ecrPolicy = new PolicyStatement(new PolicyStatementProps { Effect = Effect.ALLOW, Actions = new[] { "ecr:*" }, Resources = new[] { "*" } }); // Setup CodeCommit cross account role access policies if required IRole codeCommitRole = null; if (!string.IsNullOrWhiteSpace(configuration.Source.CrossAccountRoleArn)) { codeCommitRole = Role.FromRoleArn(this, "CodeCommitRole", configuration.Source.CrossAccountRoleArn, new FromRoleArnOptions() { Mutable = false // Flag to indicate CDK to not modify the role }); } // Self mutation var pipeline = new CdkPipeline(this, "Pipeline", new CdkPipelineProps { PipelineName = Configuration.ProjectName, CloudAssemblyArtifact = outputArtifact, SourceAction = new CodeCommitSourceAction(new CodeCommitSourceActionProps { ActionName = "CodeCommit", Output = sourceArtifact, Repository = repository, Branch = configuration.Source.BranchName, Role = codeCommitRole, Trigger = CodeCommitTrigger.POLL }), // It synthesizes CDK code to cdk.out directory which is picked by SelfMutate stage to mutate the pipeline SynthAction = new SimpleSynthAction(new SimpleSynthActionProps { SourceArtifact = sourceArtifact, CloudAssemblyArtifact = outputArtifact, Subdirectory = "LambdaRuntimeDockerfiles/dotnet5/Infrastructure", InstallCommands = new[] { "npm install -g aws-cdk", }, BuildCommands = new[] { "dotnet build" }, SynthCommand = "cdk synth", CopyEnvironmentVariables = new[] { "SOURCE_REPOSITORY_ARN", "SOURCE_BRANCH_NAME", "SOURCE_CROSS_ACCOUNT_ROLE_ARN", "BASE_ECRS", "STAGE_ECR", "BETA_ECRS", "PROD_ECRS", "ECR_REPOSITORY_NAME", } }) }); // Stage var dockerBuild = new Project(this, "DockerBuild", new ProjectProps() { BuildSpec = BuildSpec.FromSourceFilename($"{Configuration.ProjectRoot}/DockerBuild/buildspec.yml"), Description = $"Builds and pushes image to {configuration.Ecrs.Stage}", Environment = new BuildEnvironment() { BuildImage = LinuxBuildImage.AMAZON_LINUX_2_3, Privileged = true }, Source = Amazon.CDK.AWS.CodeBuild.Source.CodeCommit(new CodeCommitSourceProps() { Repository = repository, BranchOrRef = configuration.Source.BranchName }), EnvironmentVariables = new Dictionary <string, IBuildEnvironmentVariable> { { "BASE_ECRS", new BuildEnvironmentVariable() { Value = configuration.Ecrs.Base } }, { "STAGE_ECR", new BuildEnvironmentVariable { Value = configuration.Ecrs.Stage } }, { "ECR_REPOSITORY_NAME", new BuildEnvironmentVariable { Value = configuration.EcrRepositoryName } } } }); dockerBuild.AddToRolePolicy(ecrPolicy); var dockerBuildStage = pipeline.AddStage("Stage-DockerBuild"); dockerBuildStage.AddActions(new CodeBuildAction(new CodeBuildActionProps() { Input = sourceArtifact, Project = dockerBuild, ActionName = "DockerBuild" })); // Beta var betaDockerPush = new Project(this, "Beta-DockerPush", new ProjectProps() { BuildSpec = BuildSpec.FromSourceFilename($"{Configuration.ProjectRoot}/DockerPush/buildspec.yml"), Description = $"Pushes staged image to {configuration.Ecrs.Beta}", Environment = new BuildEnvironment() { BuildImage = LinuxBuildImage.AMAZON_LINUX_2_3, Privileged = true }, Source = Amazon.CDK.AWS.CodeBuild.Source.CodeCommit(new CodeCommitSourceProps() { Repository = repository, BranchOrRef = configuration.Source.BranchName }), EnvironmentVariables = new Dictionary <string, IBuildEnvironmentVariable> { { "SOURCE_ECR", new BuildEnvironmentVariable { Value = configuration.Ecrs.Stage } }, { "ECR_REPOSITORY_NAME", new BuildEnvironmentVariable { Value = configuration.EcrRepositoryName } }, { "DESTINATION_ECRS", new BuildEnvironmentVariable { Value = configuration.Ecrs.Beta } }, { "DESTINATION_IMAGE_TAG", new BuildEnvironmentVariable { Value = "beta" } }, } }); betaDockerPush.AddToRolePolicy(ecrPolicy); var betaDockerPushStage = pipeline.AddStage("Beta-DockerPush"); betaDockerPushStage.AddActions(new CodeBuildAction(new CodeBuildActionProps() { Input = sourceArtifact, Project = betaDockerPush, ActionName = "DockerPush" })); // Manual Approval var manualApprovalStage = pipeline.AddStage("Prod-ManualApproval"); manualApprovalStage.AddActions(new ManualApprovalAction(new ManualApprovalActionProps() { ActionName = "ManualApproval" })); // Prod var prodDockerPush = new Project(this, "Prod-DockerPush", new ProjectProps() { BuildSpec = BuildSpec.FromSourceFilename($"{Configuration.ProjectRoot}/DockerPush/buildspec.yml"), Description = $"Pushes staged image to {configuration.Ecrs.Prod}", Environment = new BuildEnvironment() { BuildImage = LinuxBuildImage.AMAZON_LINUX_2_3, Privileged = true }, Source = Amazon.CDK.AWS.CodeBuild.Source.CodeCommit(new CodeCommitSourceProps() { Repository = repository, BranchOrRef = "dotnet5/cdk" }), EnvironmentVariables = new Dictionary <string, IBuildEnvironmentVariable> { { "SOURCE_ECR", new BuildEnvironmentVariable { Value = configuration.Ecrs.Stage } }, { "ECR_REPOSITORY_NAME", new BuildEnvironmentVariable { Value = configuration.EcrRepositoryName } }, { "DESTINATION_ECRS", new BuildEnvironmentVariable { Value = configuration.Ecrs.Prod } }, { "DESTINATION_IMAGE_TAG", new BuildEnvironmentVariable { Value = "beta" } }, // Prod images are also tagged as beta } }); prodDockerPush.AddToRolePolicy(ecrPolicy); var prodDockerPushStage = pipeline.AddStage("Prod-DockerPush"); prodDockerPushStage.AddActions(new CodeBuildAction(new CodeBuildActionProps() { Input = sourceArtifact, Project = prodDockerPush, ActionName = "DockerPush" })); }
public WorkshopPipelineStack(Construct parent, string id, IStackProps props = null) : base(parent, id, props) { // Creates a CodeCommit repository called 'WorkshopRepo' var repo = new Repository(this, "WorkshopRepo", new RepositoryProps { RepositoryName = "WorkshopRepo" }); // Defines the artifact representing the sourcecode var sourceArtifact = new Artifact_(); // Defines the artifact representing the cloud assembly // (cloudformation template + all other assets) var cloudAssemblyArtifact = new Artifact_(); // The basic pipeline declaration. This sets the initial structure // of our pipeline var pipeline = new CdkPipeline(this, "Pipeline", new CdkPipelineProps { PipelineName = "WorkshopPipeline", CloudAssemblyArtifact = cloudAssemblyArtifact, // Generates the source artifact from the repo we created in the last step SourceAction = new CodeCommitSourceAction(new CodeCommitSourceActionProps { ActionName = "CodeCommit", // Any Git-based source control Output = sourceArtifact, // Indicates where the artifact is stored Repository = repo // Designates the repo to draw code from }), // Builds our source code outlined above into a could assembly artifact SynthAction = SimpleSynthAction.StandardNpmSynth(new StandardNpmSynthOptions { SourceArtifact = sourceArtifact, // Where to get source code to build CloudAssemblyArtifact = cloudAssemblyArtifact, // Where to place built source InstallCommands = new [] { "npm install -g aws-cdk", "sudo apt-get install -y dotnet-sdk-3.1" }, BuildCommands = new [] { "dotnet build" } // Language-specific build cmd }) }); var deploy = new WorkshopPipelineStage(this, "Deploy"); var deployStage = pipeline.AddApplicationStage(deploy); deployStage.AddActions(new ShellScriptAction(new ShellScriptActionProps { ActionName = "TestViewerEndpoint", UseOutputs = new Dictionary <string, StackOutput> { { "ENDPOINT_URL", pipeline.StackOutput(deploy.HCViewerUrl) } }, Commands = new string[] { "curl -Ssf $ENDPOINT_URL" } })); deployStage.AddActions(new ShellScriptAction(new ShellScriptActionProps { ActionName = "TestAPIGatewayEndpoint", UseOutputs = new Dictionary <string, StackOutput> { { "ENDPOINT_URL", pipeline.StackOutput(deploy.HCEndpoint) } }, Commands = new string[] { "curl -Ssf $ENDPOINT_URL/", "curl -Ssf $ENDPOINT_URL/hello", "curl -Ssf $ENDPOINT_URL/test" } })); }
internal PipelineStack( Construct scope, string id, string ecrRepositoryName, string framework, string channel, string dockerBuildImage, Configuration configuration, IStackProps props = null) : base(scope, $"{id}-{framework}", props) { var repository = Repository.FromRepositoryArn(this, "Repository", configuration.Source.RepositoryArn); var sourceArtifact = new Artifact_(); var outputArtifact = new Artifact_(); var ecrPolicy = new PolicyStatement(new PolicyStatementProps { Effect = Effect.ALLOW, Actions = new[] { "ecr:*" }, Resources = new[] { "*" } }); // Setup CodeCommit cross account role access policies if required IRole codeCommitRole = null; if (!string.IsNullOrWhiteSpace(configuration.Source.CrossAccountRoleArn)) { codeCommitRole = Role.FromRoleArn(this, "CodeCommitRole", configuration.Source.CrossAccountRoleArn, new FromRoleArnOptions { Mutable = false // Flag to indicate CDK to not modify the role }); } // Strict ordering is required to make sure CloudFormation template doesn't result in false difference var environmentVariablesToCopy = System.Environment.GetEnvironmentVariables() .Keys.Cast <string>() .Where(variable => variable.StartsWith("AWS_LAMBDA_")) .OrderBy(variable => variable); // Self mutation // TODO: DOTNET-6085 - Migration from CDKPipeline to CodePipeline const string cdkCliVersion = "1.159.0"; var pipeline = new CdkPipeline(this, "Pipeline", new CdkPipelineProps { PipelineName = $"{id}-{framework}", CloudAssemblyArtifact = outputArtifact, CdkCliVersion = cdkCliVersion, SourceAction = new CodeCommitSourceAction(new CodeCommitSourceActionProps { ActionName = "CodeCommit", Output = sourceArtifact, Repository = repository, Branch = configuration.Source.BranchName, Role = codeCommitRole, Trigger = CodeCommitTrigger.POLL }), // It synthesizes CDK code to cdk.out directory which is picked by SelfMutate stage to mutate the pipeline SynthAction = new SimpleSynthAction(new SimpleSynthActionProps { SourceArtifact = sourceArtifact, CloudAssemblyArtifact = outputArtifact, Subdirectory = "LambdaRuntimeDockerfiles/Infrastructure", InstallCommands = new[] { $"npm install -g aws-cdk@{cdkCliVersion}", }, BuildCommands = new[] { "dotnet build" }, SynthCommand = "cdk synth", CopyEnvironmentVariables = environmentVariablesToCopy.ToArray() }) }); var stageEcr = GetStageEcr(this, ecrRepositoryName, configuration); var dockerBuildStage = pipeline.AddStage("Stage-DockerBuild"); // Stage // Build AMD64 image var dockerBuildAmd64 = new Project(this, "DockerBuild-amd64", new ProjectProps { BuildSpec = BuildSpec.FromSourceFilename($"{Configuration.ProjectRoot}/DockerBuild/buildspec.yml"), Description = $"Builds and pushes image to {stageEcr}", Environment = new BuildEnvironment { BuildImage = LinuxBuildImage.AMAZON_LINUX_2_3, Privileged = true }, Source = Amazon.CDK.AWS.CodeBuild.Source.CodeCommit(new CodeCommitSourceProps { Repository = repository, BranchOrRef = configuration.Source.BranchName }), EnvironmentVariables = new Dictionary <string, IBuildEnvironmentVariable> { { "AWS_LAMBDA_STAGE_ECR", new BuildEnvironmentVariable { Value = stageEcr } }, { "AWS_LAMBDA_ECR_REPOSITORY_NAME", new BuildEnvironmentVariable { Value = ecrRepositoryName } }, { "AWS_LAMBDA_ARCHITECTURE", new BuildEnvironmentVariable { Value = "amd64" } }, { "AWS_LAMBDA_POWERSHELL_VERSION", new BuildEnvironmentVariable { Value = PowershellAmd64 } }, { "AWS_LAMBDA_IMAGE_TAG", new BuildEnvironmentVariable { Value = configuration.BaseImageAMD64Tags[framework] } }, { "AWS_LAMBDA_DOTNET_FRAMEWORK_VERSION", new BuildEnvironmentVariable { Value = framework } }, { "AWS_LAMBDA_DOTNET_FRAMEWORK_CHANNEL", new BuildEnvironmentVariable { Value = channel } } } }); dockerBuildAmd64.AddToRolePolicy(ecrPolicy); dockerBuildStage.AddActions(new CodeBuildAction(new CodeBuildActionProps { Input = sourceArtifact, Project = dockerBuildAmd64, ActionName = "amd64" })); if (configuration.DockerARM64Images.Contains(framework)) { // Build ARM64 image var dockerBuildArm64 = new Project(this, "DockerBuild-arm64", new ProjectProps { BuildSpec = BuildSpec.FromSourceFilename($"{Configuration.ProjectRoot}/DockerBuild/buildspec.yml"), Description = $"Builds and pushes image to {stageEcr}", Environment = new BuildEnvironment { BuildImage = LinuxBuildImage.AMAZON_LINUX_2_ARM, Privileged = true }, Source = Amazon.CDK.AWS.CodeBuild.Source.CodeCommit(new CodeCommitSourceProps { Repository = repository, BranchOrRef = configuration.Source.BranchName }), EnvironmentVariables = new Dictionary <string, IBuildEnvironmentVariable> { { "AWS_LAMBDA_STAGE_ECR", new BuildEnvironmentVariable { Value = stageEcr } }, { "AWS_LAMBDA_ECR_REPOSITORY_NAME", new BuildEnvironmentVariable { Value = ecrRepositoryName } }, { "AWS_LAMBDA_ARCHITECTURE", new BuildEnvironmentVariable { Value = "arm64" } }, { "AWS_LAMBDA_POWERSHELL_VERSION", new BuildEnvironmentVariable { Value = PowershellArm64 } }, { "AWS_LAMBDA_IMAGE_TAG", new BuildEnvironmentVariable { Value = configuration.BaseImageARM64Tags[framework] } }, { "AWS_LAMBDA_DOTNET_FRAMEWORK_VERSION", new BuildEnvironmentVariable { Value = framework } }, { "AWS_LAMBDA_DOTNET_FRAMEWORK_CHANNEL", new BuildEnvironmentVariable { Value = channel } } } }); dockerBuildArm64.AddToRolePolicy(ecrPolicy); dockerBuildStage.AddActions(new CodeBuildAction(new CodeBuildActionProps { Input = sourceArtifact, Project = dockerBuildArm64, ActionName = "arm64" })); } // Create multi arch image manifest var dockerImageManifest = new Project(this, "DockerImageManifest", new ProjectProps { BuildSpec = BuildSpec.FromSourceFilename($"{Configuration.ProjectRoot}/DockerImageManifest/buildspec.yml"), Description = $"Creates image manifest and pushes to {stageEcr}", Environment = new BuildEnvironment { BuildImage = LinuxBuildImage.AMAZON_LINUX_2_3, Privileged = true }, Source = Amazon.CDK.AWS.CodeBuild.Source.CodeCommit(new CodeCommitSourceProps { Repository = repository, BranchOrRef = configuration.Source.BranchName }), EnvironmentVariables = new Dictionary <string, IBuildEnvironmentVariable> { { "AWS_LAMBDA_STAGE_ECR", new BuildEnvironmentVariable { Value = stageEcr } }, { "AWS_LAMBDA_ECR_REPOSITORY_NAME", new BuildEnvironmentVariable { Value = ecrRepositoryName } }, { "AWS_LAMBDA_MULTI_ARCH_IMAGE_TAG", new BuildEnvironmentVariable { Value = BaseImageMultiArch } }, { "AWS_LAMBDA_AMD64_IMAGE_TAG", new BuildEnvironmentVariable { Value = configuration.BaseImageAMD64Tags[framework] } }, { "AWS_LAMBDA_ARM64_IMAGE_TAG", new BuildEnvironmentVariable { Value = configuration.BaseImageARM64Tags[framework] } }, { "AWS_LAMBDA_INCLUDE_ARM64", new BuildEnvironmentVariable { Value = configuration.DockerARM64Images.Contains(framework).ToString() } }, } }); dockerImageManifest.AddToRolePolicy(ecrPolicy); var dockerImageManifestStage = pipeline.AddStage("DockerImageManifest"); dockerImageManifestStage.AddActions(new CodeBuildAction(new CodeBuildActionProps { Input = sourceArtifact, Project = dockerImageManifest, ActionName = "DockerImageManifest" })); // Smoke test AMD64 image var amd64SmokeTests = new Project(this, "SmokeTests-amd64", new ProjectProps { BuildSpec = BuildSpec.FromSourceFilename($"{Configuration.ProjectRoot}/SmokeTests/buildspec.yml"), Description = "Runs smoke tests on the built image.", Environment = new BuildEnvironment { BuildImage = LinuxBuildImage.AMAZON_LINUX_2_3, Privileged = true }, Source = Amazon.CDK.AWS.CodeBuild.Source.CodeCommit(new CodeCommitSourceProps { Repository = repository, BranchOrRef = configuration.Source.BranchName }), EnvironmentVariables = new Dictionary <string, IBuildEnvironmentVariable> { { "AWS_LAMBDA_SOURCE_ECR", new BuildEnvironmentVariable { Value = stageEcr } }, { "AWS_LAMBDA_ECR_REPOSITORY_NAME", new BuildEnvironmentVariable { Value = ecrRepositoryName } }, { "AWS_LAMBDA_SOURCE_IMAGE_TAG", new BuildEnvironmentVariable { Value = BaseImageMultiArch } }, { "AWS_LAMBDA_POWERSHELL_VERSION", new BuildEnvironmentVariable { Value = PowershellAmd64 } }, { "AWS_LAMBDA_DOTNET_FRAMEWORK_VERSION", new BuildEnvironmentVariable { Value = framework } }, { "AWS_LAMBDA_DOTNET_FRAMEWORK_CHANNEL", new BuildEnvironmentVariable { Value = channel } }, { "AWS_LAMBDA_DOTNET_BUILD_IMAGE", new BuildEnvironmentVariable { Value = dockerBuildImage } }, } }); var smokeTestsPolicy = new PolicyStatement(new PolicyStatementProps { Effect = Effect.ALLOW, Actions = new[] { "sts:*", "iam:*", "ecr:*", "lambda:*" }, Resources = new[] { "*" } }); amd64SmokeTests.AddToRolePolicy(smokeTestsPolicy); var smokeTestsStage = pipeline.AddStage("SmokeTests"); smokeTestsStage.AddActions(new CodeBuildAction(new CodeBuildActionProps { Input = sourceArtifact, Project = amd64SmokeTests, ActionName = "amd64" })); if (configuration.DockerARM64Images.Contains(framework)) { // Smoke test ARM64 image var arm64SmokeTests = new Project(this, "SmokeTests-arm64", new ProjectProps { BuildSpec = BuildSpec.FromSourceFilename($"{Configuration.ProjectRoot}/SmokeTests/buildspec.yml"), Description = "Runs smoke tests on the built image.", Environment = new BuildEnvironment { BuildImage = LinuxBuildImage.AMAZON_LINUX_2_ARM, Privileged = true }, Source = Amazon.CDK.AWS.CodeBuild.Source.CodeCommit(new CodeCommitSourceProps { Repository = repository, BranchOrRef = configuration.Source.BranchName }), EnvironmentVariables = new Dictionary <string, IBuildEnvironmentVariable> { { "AWS_LAMBDA_SOURCE_ECR", new BuildEnvironmentVariable { Value = stageEcr } }, { "AWS_LAMBDA_ECR_REPOSITORY_NAME", new BuildEnvironmentVariable { Value = ecrRepositoryName } }, { "AWS_LAMBDA_SOURCE_IMAGE_TAG", new BuildEnvironmentVariable { Value = BaseImageMultiArch } }, { "AWS_LAMBDA_POWERSHELL_VERSION", new BuildEnvironmentVariable { Value = PowershellArm64 } }, { "AWS_LAMBDA_DOTNET_FRAMEWORK_VERSION", new BuildEnvironmentVariable { Value = framework } }, { "AWS_LAMBDA_DOTNET_FRAMEWORK_CHANNEL", new BuildEnvironmentVariable { Value = channel } }, { "AWS_LAMBDA_DOTNET_BUILD_IMAGE", new BuildEnvironmentVariable { Value = dockerBuildImage } }, } }); arm64SmokeTests.AddToRolePolicy(smokeTestsPolicy); smokeTestsStage.AddActions(new CodeBuildAction(new CodeBuildActionProps { Input = sourceArtifact, Project = arm64SmokeTests, ActionName = "arm64" })); } // Beta if (!string.IsNullOrWhiteSpace(configuration.Ecrs.Beta)) { var betaDockerPush = new Project(this, "Beta-DockerPush", new ProjectProps { BuildSpec = BuildSpec.FromSourceFilename($"{Configuration.ProjectRoot}/DockerPush/buildspec.yml"), Description = $"Pushes staged image to {configuration.Ecrs.Beta}", Environment = new BuildEnvironment { BuildImage = LinuxBuildImage.AMAZON_LINUX_2_3, Privileged = true }, Source = Amazon.CDK.AWS.CodeBuild.Source.CodeCommit(new CodeCommitSourceProps { Repository = repository, BranchOrRef = configuration.Source.BranchName }), EnvironmentVariables = new Dictionary <string, IBuildEnvironmentVariable> { { "AWS_LAMBDA_SOURCE_ECR", new BuildEnvironmentVariable { Value = stageEcr } }, { "AWS_LAMBDA_ECR_REPOSITORY_NAME", new BuildEnvironmentVariable { Value = ecrRepositoryName } }, { "AWS_LAMBDA_DESTINATION_ECRS", new BuildEnvironmentVariable { Value = configuration.Ecrs.Beta } }, { "AWS_LAMBDA_MULTI_ARCH_IMAGE_TAG", new BuildEnvironmentVariable { Value = BaseImageMultiArch } }, { "AWS_LAMBDA_AMD64_IMAGE_TAG", new BuildEnvironmentVariable { Value = configuration.BaseImageAMD64Tags[framework] } }, { "AWS_LAMBDA_ARM64_IMAGE_TAG", new BuildEnvironmentVariable { Value = configuration.BaseImageARM64Tags[framework] } }, { "AWS_LAMBDA_INCLUDE_ARM64", new BuildEnvironmentVariable { Value = configuration.DockerARM64Images.Contains(framework).ToString() } }, } }); betaDockerPush.AddToRolePolicy(ecrPolicy); var betaDockerPushStage = pipeline.AddStage("Beta-DockerPush"); betaDockerPushStage.AddActions(new CodeBuildAction(new CodeBuildActionProps { Input = sourceArtifact, Project = betaDockerPush, ActionName = "DockerPush" })); } // Prod if (!string.IsNullOrWhiteSpace(configuration.Ecrs.Prod)) { // Manual Approval var manualApprovalStage = pipeline.AddStage("Prod-ManualApproval"); manualApprovalStage.AddActions(new ManualApprovalAction(new ManualApprovalActionProps { ActionName = "ManualApproval" })); var prodDockerPush = new Project(this, "Prod-DockerPush", new ProjectProps { BuildSpec = BuildSpec.FromSourceFilename($"{Configuration.ProjectRoot}/DockerPush/buildspec.yml"), Description = $"Pushes staged image to {configuration.Ecrs.Prod}", Environment = new BuildEnvironment { BuildImage = LinuxBuildImage.AMAZON_LINUX_2_3, Privileged = true }, Source = Amazon.CDK.AWS.CodeBuild.Source.CodeCommit(new CodeCommitSourceProps { Repository = repository, BranchOrRef = configuration.Source.BranchName }), EnvironmentVariables = new Dictionary <string, IBuildEnvironmentVariable> { { "AWS_LAMBDA_SOURCE_ECR", new BuildEnvironmentVariable { Value = stageEcr } }, { "AWS_LAMBDA_ECR_REPOSITORY_NAME", new BuildEnvironmentVariable { Value = ecrRepositoryName } }, { "AWS_LAMBDA_DESTINATION_ECRS", new BuildEnvironmentVariable { Value = configuration.Ecrs.Prod } }, { "AWS_LAMBDA_MULTI_ARCH_IMAGE_TAG", new BuildEnvironmentVariable { Value = BaseImageMultiArch } }, { "AWS_LAMBDA_AMD64_IMAGE_TAG", new BuildEnvironmentVariable { Value = configuration.BaseImageAMD64Tags[framework] } }, { "AWS_LAMBDA_ARM64_IMAGE_TAG", new BuildEnvironmentVariable { Value = configuration.BaseImageARM64Tags[framework] } }, { "AWS_LAMBDA_INCLUDE_ARM64", new BuildEnvironmentVariable { Value = configuration.DockerARM64Images.Contains(framework).ToString() } }, } }); prodDockerPush.AddToRolePolicy(ecrPolicy); var prodDockerPushStage = pipeline.AddStage("Prod-DockerPush"); prodDockerPushStage.AddActions(new CodeBuildAction(new CodeBuildActionProps { Input = sourceArtifact, Project = prodDockerPush, ActionName = "DockerPush" })); } }
internal PipelineStack(Construct scope, string id, Configuration configuration, IStackProps props = null) : base(scope, id, props) { var repository = Repository.FromRepositoryArn(this, "Repository", configuration.Source.RepositoryArn); var sourceArtifact = new Artifact_(); var outputArtifact = new Artifact_(); var ecrPolicy = new PolicyStatement(new PolicyStatementProps { Effect = Effect.ALLOW, Actions = new[] { "ecr:*" }, Resources = new[] { "*" } }); // Setup CodeCommit cross account role access policies if required IRole codeCommitRole = null; if (!string.IsNullOrWhiteSpace(configuration.Source.CrossAccountRoleArn)) { codeCommitRole = Role.FromRoleArn(this, "CodeCommitRole", configuration.Source.CrossAccountRoleArn, new FromRoleArnOptions { Mutable = false // Flag to indicate CDK to not modify the role }); } // Strict ordering is required to make sure CloudFormation template doesn't result in false difference var environmentVariablesToCopy = System.Environment.GetEnvironmentVariables() .Keys.Cast <string>() .Where(variable => variable.StartsWith("AWS_LAMBDA_")) .OrderBy(variable => variable); // Self mutation var pipeline = new CdkPipeline(this, "Pipeline", new CdkPipelineProps { PipelineName = Configuration.ProjectName, CloudAssemblyArtifact = outputArtifact, SourceAction = new CodeCommitSourceAction(new CodeCommitSourceActionProps { ActionName = "CodeCommit", Output = sourceArtifact, Repository = repository, Branch = configuration.Source.BranchName, Role = codeCommitRole, Trigger = CodeCommitTrigger.POLL }), // It synthesizes CDK code to cdk.out directory which is picked by SelfMutate stage to mutate the pipeline SynthAction = new SimpleSynthAction(new SimpleSynthActionProps { SourceArtifact = sourceArtifact, CloudAssemblyArtifact = outputArtifact, Subdirectory = "LambdaRuntimeDockerfiles/dotnet5/Infrastructure", InstallCommands = new[] { "npm install -g aws-cdk", }, BuildCommands = new[] { "dotnet build" }, SynthCommand = "cdk synth", CopyEnvironmentVariables = environmentVariablesToCopy.ToArray() }) }); var stageEcr = GetStageEcr(this, configuration); // Stage var dockerBuild = new Project(this, "DockerBuild", new ProjectProps { BuildSpec = BuildSpec.FromSourceFilename($"{Configuration.ProjectRoot}/DockerBuild/buildspec.yml"), Description = $"Builds and pushes image to {stageEcr}", Environment = new BuildEnvironment { BuildImage = LinuxBuildImage.AMAZON_LINUX_2_3, Privileged = true }, Source = Amazon.CDK.AWS.CodeBuild.Source.CodeCommit(new CodeCommitSourceProps { Repository = repository, BranchOrRef = configuration.Source.BranchName }), EnvironmentVariables = new Dictionary <string, IBuildEnvironmentVariable> { { "AWS_LAMBDA_STAGE_ECR", new BuildEnvironmentVariable { Value = stageEcr } }, { "AWS_LAMBDA_ECR_REPOSITORY_NAME", new BuildEnvironmentVariable { Value = configuration.EcrRepositoryName } } } }); dockerBuild.AddToRolePolicy(ecrPolicy); var dockerBuildStage = pipeline.AddStage("Stage-DockerBuild"); dockerBuildStage.AddActions(new CodeBuildAction(new CodeBuildActionProps { Input = sourceArtifact, Project = dockerBuild, ActionName = "DockerBuild" })); var smokeTests = new Project(this, "SmokeTests", new ProjectProps { BuildSpec = BuildSpec.FromSourceFilename($"{Configuration.ProjectRoot}/SmokeTests/buildspec.yml"), Description = "Runs smoke tests on the built image.", Environment = new BuildEnvironment { BuildImage = LinuxBuildImage.AMAZON_LINUX_2_3, Privileged = true }, Source = Amazon.CDK.AWS.CodeBuild.Source.CodeCommit(new CodeCommitSourceProps { Repository = repository, BranchOrRef = configuration.Source.BranchName }), EnvironmentVariables = new Dictionary <string, IBuildEnvironmentVariable> { { "AWS_LAMBDA_SOURCE_ECR", new BuildEnvironmentVariable { Value = stageEcr } }, { "AWS_LAMBDA_ECR_REPOSITORY_NAME", new BuildEnvironmentVariable { Value = configuration.EcrRepositoryName } }, } }); var smokeTestsPolicy = new PolicyStatement(new PolicyStatementProps { Effect = Effect.ALLOW, Actions = new[] { "sts:*", "iam:*", "ecr:*", "lambda:*" }, Resources = new[] { "*" } }); smokeTests.AddToRolePolicy(smokeTestsPolicy); var smokeTestsStage = pipeline.AddStage("SmokeTests"); smokeTestsStage.AddActions(new CodeBuildAction(new CodeBuildActionProps { Input = sourceArtifact, Project = smokeTests, ActionName = "SmokeTests" })); // Beta if (!string.IsNullOrWhiteSpace(configuration.Ecrs.Beta)) { var betaDockerPush = new Project(this, "Beta-DockerPush", new ProjectProps { BuildSpec = BuildSpec.FromSourceFilename($"{Configuration.ProjectRoot}/DockerPush/buildspec.yml"), Description = $"Pushes staged image to {configuration.Ecrs.Beta}", Environment = new BuildEnvironment { BuildImage = LinuxBuildImage.AMAZON_LINUX_2_3, Privileged = true }, Source = Amazon.CDK.AWS.CodeBuild.Source.CodeCommit(new CodeCommitSourceProps { Repository = repository, BranchOrRef = configuration.Source.BranchName }), EnvironmentVariables = new Dictionary <string, IBuildEnvironmentVariable> { { "AWS_LAMBDA_SOURCE_ECR", new BuildEnvironmentVariable { Value = stageEcr } }, { "AWS_LAMBDA_ECR_REPOSITORY_NAME", new BuildEnvironmentVariable { Value = configuration.EcrRepositoryName } }, { "AWS_LAMBDA_DESTINATION_ECRS", new BuildEnvironmentVariable { Value = configuration.Ecrs.Beta } }, { "AWS_LAMBDA_DESTINATION_IMAGE_TAG", new BuildEnvironmentVariable { Value = "beta" } }, } }); betaDockerPush.AddToRolePolicy(ecrPolicy); var betaDockerPushStage = pipeline.AddStage("Beta-DockerPush"); betaDockerPushStage.AddActions(new CodeBuildAction(new CodeBuildActionProps { Input = sourceArtifact, Project = betaDockerPush, ActionName = "DockerPush" })); } // Prod if (!string.IsNullOrWhiteSpace(configuration.Ecrs.Prod)) { // Manual Approval var manualApprovalStage = pipeline.AddStage("Prod-ManualApproval"); manualApprovalStage.AddActions(new ManualApprovalAction(new ManualApprovalActionProps { ActionName = "ManualApproval" })); var prodDockerPush = new Project(this, "Prod-DockerPush", new ProjectProps { BuildSpec = BuildSpec.FromSourceFilename($"{Configuration.ProjectRoot}/DockerPush/buildspec.yml"), Description = $"Pushes staged image to {configuration.Ecrs.Prod}", Environment = new BuildEnvironment { BuildImage = LinuxBuildImage.AMAZON_LINUX_2_3, Privileged = true }, Source = Amazon.CDK.AWS.CodeBuild.Source.CodeCommit(new CodeCommitSourceProps { Repository = repository, BranchOrRef = "dotnet5/cdk" }), EnvironmentVariables = new Dictionary <string, IBuildEnvironmentVariable> { { "AWS_LAMBDA_SOURCE_ECR", new BuildEnvironmentVariable { Value = stageEcr } }, { "AWS_LAMBDA_ECR_REPOSITORY_NAME", new BuildEnvironmentVariable { Value = configuration.EcrRepositoryName } }, { "AWS_LAMBDA_DESTINATION_ECRS", new BuildEnvironmentVariable { Value = configuration.Ecrs.Prod } }, { "AWS_LAMBDA_DESTINATION_IMAGE_TAG", new BuildEnvironmentVariable { Value = "beta" } }, // Prod images are also tagged as beta } }); prodDockerPush.AddToRolePolicy(ecrPolicy); var prodDockerPushStage = pipeline.AddStage("Prod-DockerPush"); prodDockerPushStage.AddActions(new CodeBuildAction(new CodeBuildActionProps { Input = sourceArtifact, Project = prodDockerPush, ActionName = "DockerPush" })); } }