{"id":27049,"date":"2026-01-13T18:05:10","date_gmt":"2026-01-13T12:35:10","guid":{"rendered":"https:\/\/www.invensislearning.com\/blog\/?p=27049"},"modified":"2026-03-03T12:21:25","modified_gmt":"2026-03-03T06:51:25","slug":"how-to-build-ci-cd-pipeline-on-aws","status":"publish","type":"post","link":"https:\/\/www.invensislearning.com\/blog\/how-to-build-ci-cd-pipeline-on-aws\/","title":{"rendered":"How to Build a CI\/CD Pipeline on AWS: Complete Step-by-Step Guide"},"content":{"rendered":"<p><span style=\"font-weight: 400;\">Continuous Integration and Continuous Deployment (CI\/CD) has become the cornerstone of modern software development, with 87% of high-performing DevOps teams deploying code multiple times per day, compared to once per month for low performers. AWS, commanding 32% of the global cloud infrastructure market, provides a comprehensive suite of native CI\/CD services that integrate seamlessly with its vast ecosystem, enabling organizations to build robust, scalable deployment pipelines without managing infrastructure.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Manual deployment processes, developers manually building code, operations teams manually deploying to servers, configuration drift across environments, and deployment anxiety every release cycle create bottlenecks that slow feature delivery, introduce human errors, and prevent the rapid iteration modern businesses demand. These pain points compound as applications scale and teams grow, making automated CI\/CD pipelines not just beneficial but essential for competitive software delivery.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">This comprehensive guide walks you through building a complete CI\/CD pipeline on AWS from scratch, covering every component: setting up source control with AWS CodeCommit, configuring automated builds with AWS CodeBuild, deploying applications with AWS CodeDeploy, and orchestrating the entire workflow with AWS CodePipeline. You\u2019ll learn practical implementation with real code examples, including buildspec.yml and appspec.yml configurations, understand AWS service integration patterns, discover security and optimization best practices, and gain troubleshooting strategies for common pipeline issues.<\/span><\/p>\n<p><strong>Table of Contents:<\/strong><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><a class=\"smooth-scroll-link\" href=\"#scroll1\">Understanding CI\/CD on AWS<\/a><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><a class=\"smooth-scroll-link\" href=\"#scroll2\">Prerequisites and Setup<\/a><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><a class=\"smooth-scroll-link\" href=\"#scroll3\">Step 1 &#8211; Setting Up Source Control with AWS CodeCommit<\/a><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><a class=\"smooth-scroll-link\" href=\"#scroll4\">Step 2 &#8211; Configuring Build with AWS CodeBuild<\/a><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><a class=\"smooth-scroll-link\" href=\"#scroll5\">Step 3 &#8211; Configuring Deployment with AWS CodeDeploy<\/a><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><a class=\"smooth-scroll-link\" href=\"#scroll6\">Step 4 &#8211; Creating the Complete Pipeline with AWS CodePipeline<\/a><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><a class=\"smooth-scroll-link\" href=\"#scroll7\">Advanced Configurations and Best Practices<\/a><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><a class=\"smooth-scroll-link\" href=\"#scroll8\">Monitoring, Logging, and Troubleshooting<\/a><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><a class=\"smooth-scroll-link\" href=\"#scroll9\">Conclusion<\/a><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><a class=\"smooth-scroll-link\" href=\"#scroll10\">Frequently Asked Questions<\/a><\/li>\n<\/ul>\n<h2 id=\"scroll1\"><b>Understanding CI\/CD on AWS<\/b><\/h2>\n<h3><b>What is CI\/CD?<\/b><\/h3>\n<p><a href=\"https:\/\/www.invensislearning.com\/blog\/devops-continuous-integration\/\" target=\"_blank\" rel=\"noopener\">Continuous Integration (CI)<\/a><span style=\"font-weight: 400;\"> is the practice of automatically building and testing code every time developers commit changes to version control. Rather than integrating code quarterly or monthly (risking massive merge conflicts and integration issues), CI integrates multiple times daily, catching integration problems early when they\u2019re easiest to fix. Automated tests run on every commit, providing rapid feedback about code quality and preventing broken code from reaching downstream environments.<\/span><\/p>\n<p><a href=\"https:\/\/www.invensislearning.com\/blog\/devops-continuous-delivery-vs-deployment\/\" target=\"_blank\" rel=\"noopener\">Continuous Deployment vs. Continuous Delivery<\/a><span style=\"font-weight: 400;\">: These terms are often conflated but represent different levels of automation. <\/span><a href=\"https:\/\/www.invensislearning.com\/blog\/devops-continuous-delivery\/\" target=\"_blank\" rel=\"noopener\">Continuous Delivery<\/a><span style=\"font-weight: 400;\"> automatically builds, tests, and prepares code for production deployment, but it still requires manual approval before production release, introducing human gates for business-critical decisions. <\/span>Continuous Deployment<span style=\"font-weight: 400;\"> goes further by automatically deploying every code change that passes automated tests directly to production without human intervention, maximizing deployment frequency while requiring mature testing and monitoring practices.<\/span><\/p>\n<p><b>Benefits for development teams<\/b><span style=\"font-weight: 400;\">: CI\/CD transforms development workflows by providing: <\/span>Faster feedback loops (developers learn within minutes if commits break tests), Reduced integration risk (small frequent integrations versus large risky merges), Automated quality gates (tests, security scans, compliance checks run automatically), Deployment confidence (repeatable automated processes eliminate human error), and Accelerated feature velocity<span style=\"font-weight: 400;\"> (remove deployment bottlenecks enabling multiple daily releases).<\/span><\/p>\n<h3><b>AWS CI\/CD Service Ecosystem<\/b><\/h3>\n<p><span style=\"font-weight: 400;\">AWS provides comprehensive native services covering the entire CI\/CD lifecycle:<\/span><\/p>\n<p><img class=\"aligncenter wp-image-27051 size-full\" title=\"AWS CI\/CD Pipeline Architecture Details\" src=\"https:\/\/www.invensislearning.com\/blog\/wp-content\/uploads\/2026\/01\/aws-ci-cd-pipeline-architecture.jpg\" alt=\"AWS CI\/CD Pipeline Architecture Details\" width=\"1000\" height=\"594\" srcset=\"https:\/\/www.invensislearning.com\/blog\/wp-content\/uploads\/2026\/01\/aws-ci-cd-pipeline-architecture.jpg 1000w, https:\/\/www.invensislearning.com\/blog\/wp-content\/uploads\/2026\/01\/aws-ci-cd-pipeline-architecture-300x178.jpg 300w, https:\/\/www.invensislearning.com\/blog\/wp-content\/uploads\/2026\/01\/aws-ci-cd-pipeline-architecture-768x456.jpg 768w, https:\/\/www.invensislearning.com\/blog\/wp-content\/uploads\/2026\/01\/aws-ci-cd-pipeline-architecture-696x413.jpg 696w, https:\/\/www.invensislearning.com\/blog\/wp-content\/uploads\/2026\/01\/aws-ci-cd-pipeline-architecture-707x420.jpg 707w\" sizes=\"(max-width: 1000px) 100vw, 1000px\" \/><\/p>\n<p><span style=\"font-weight: 400;\">AWS CodePipeline serves as the orchestration engine, the workflow coordinator connecting source control, build, test, and deployment stages into automated pipelines. CodePipeline monitors source repositories for changes, triggers builds when commits occur, promotes artifacts through environments, and provides a visualization of deployment progress across stages.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">AWS CodeCommit offers a fully managed, Git-based source control service with private repositories and standard Git functionality, plus AWS integrations. While many teams use GitHub or GitLab, CodeCommit offers native AWS integration, no server management, and automatic scaling, ideal for organizations that prefer AWS-native solutions or require tighter AWS security integration.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">AWS CodeBuild provides a fully managed build service, eliminating the need to provision and manage Jenkins or other build servers. CodeBuild compiles code, runs tests, produces deployment artifacts, and scales automatically based on build workload. You define build specifications in <\/span><span style=\"font-weight: 400;\">buildspec.yml<\/span><span style=\"font-weight: 400;\"> files stored alongside the source code, ensuring build processes are version-controlled alongside the application code.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">AWS CodeDeploy automates application deployments to compute resources, EC2 instances, on-premise servers, Lambda functions, or ECS services. CodeDeploy handles deployment orchestration, rolling updates, health checks, and automatic rollback when deployments fail, supporting complex strategies such as blue-green deployments and canary releases.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Integration with third-party tools: While AWS native services provide comprehensive CI\/CD capabilities, AWS CodePipeline integrates seamlessly with popular third-party tools, including GitHub\/GitLab\/Bitbucket for source control, Jenkins for builds, Terraform for infrastructure provisioning, and various testing\/security scanning tools. This flexibility lets teams adopt AWS CI\/CD incrementally, integrating with existing tools while gradually transitioning to AWS-native services.<\/span><\/p>\n<table>\n<tbody>\n<tr>\n<td><b>PRO TIP: WHEN TO USE AWS NATIVE VS THIRD-PARTY TOOLS<\/b><\/p>\n<p><b>Choose AWS native services (CodePipeline, CodeBuild, CodeDeploy) when:<\/b><span style=\"font-weight: 400;\"> You want zero server management (fully managed, automatic scaling), you\u2019re already heavily invested in the AWS ecosystem, you need tight AWS service integration (IAM, CloudWatch, S3), or you want predictable AWS-consolidated billing. AWS native tools excel for teams that want simplicity and tight AWS integration without managing infrastructure.<\/span><\/p>\n<p><b>Consider third-party tools (Jenkins, GitHub Actions, GitLab CI) when:<\/b><span style=\"font-weight: 400;\"> you need a specific plugin ecosystem (Jenkins has 1500+ plugins); you have multi-cloud deployments requiring cloud-agnostic pipelines; your team has deep expertise in specific tools; or you need features not yet available in AWS services. Hybrid approaches work well, use GitHub for source control, but CodeBuild\/CodeDeploy for AWS-specific deployment tasks.<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2 id=\"scroll2\"><b>Prerequisites and Setup<\/b><\/h2>\n<h3><b>AWS Account Requirements<\/b><\/h3>\n<p><b>IAM permissions needed<\/b><span style=\"font-weight: 400;\">: Building CI\/CD pipelines requires specific IAM permissions across multiple AWS services. At minimum, you need permissions for: CodePipeline (create, update, view), CodeCommit (repository management, pull, push), CodeBuild (project management, start builds), CodeDeploy (application and deployment group management), S3 (artifact storage bucket access), IAM (role creation for service-to-service permissions), and CloudWatch (logging and monitoring access).<\/span><\/p>\n<p><span style=\"font-weight: 400;\">For learning environments, use an IAM user with administrator access. For production, follow least privilege principles creating custom IAM policies granting only necessary permissions. AWS provides managed policies like <\/span><span style=\"font-weight: 400;\">AWSCodePipelineFullAccess<\/span><span style=\"font-weight: 400;\">, <\/span><span style=\"font-weight: 400;\">AWSCodeBuildAdminAccess<\/span><span style=\"font-weight: 400;\">, and <\/span><span style=\"font-weight: 400;\">AWSCodeDeployFullAccess<\/span><span style=\"font-weight: 400;\"> as starting points, though custom policies provide tighter security.<\/span><\/p>\n<p><b>Service limits and quotas<\/b><span style=\"font-weight: 400;\">: Be aware of AWS service quotas: CodePipeline allows 300 pipelines per region (soft limit, increasable), CodeBuild supports 60 concurrent builds per region, and CodeCommit permits 1,000 repositories per region. For most projects these limits are generous, but large enterprises should review quotas and request increases proactively.<\/span><\/p>\n<h3><b>Development Environment Setup<\/b><\/h3>\n<p><b>AWS CLI installation<\/b><span style=\"font-weight: 400;\">: Install AWS Command Line Interface for programmatic AWS interaction. Download from <\/span><span style=\"font-weight: 400;\">aws.amazon.com\/cli<\/span><span style=\"font-weight: 400;\">, install for your OS (Windows\/Mac\/Linux), and configure credentials:<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Install AWS CLI (MacOS\/Linux via curl)<\/span><\/p>\n<p><span style=\"font-weight: 400;\">curl &#8220;https:\/\/awscli.amazonaws.com\/awscli-exe-linux-x86_64.zip&#8221; -o &#8220;awscliv2.zip&#8221;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">unzip awscliv2.zip<\/span><\/p>\n<p><span style=\"font-weight: 400;\">sudo .\/aws\/install<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Configure AWS credentials<\/span><\/p>\n<p><span style=\"font-weight: 400;\">aws configure<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Enter: Access Key ID, Secret Access Key, Region (us-east-1), Output format (json)<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Verify installation<\/span><\/p>\n<p><span style=\"font-weight: 400;\">aws &#8211;version<\/span><\/p>\n<p><span style=\"font-weight: 400;\">aws sts get-caller-identity\u00a0 # Confirms authentication<\/span><\/p>\n<p><b>Git configuration<\/b><span style=\"font-weight: 400;\">: Ensure Git is installed and configured:<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Install Git (if not present)<\/span><\/p>\n<p><span style=\"font-weight: 400;\">sudo apt-get install git\u00a0 # Ubuntu\/Debian<\/span><\/p>\n<p><span style=\"font-weight: 400;\">brew install git\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 # MacOS<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Configure Git identity<\/span><\/p>\n<p><span style=\"font-weight: 400;\">git config &#8211;global user.name &#8220;Your Name&#8221;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">git config &#8211;global user.email &#8220;your.email@example.com&#8221;<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Verify configuration<\/span><\/p>\n<p><span style=\"font-weight: 400;\">git config &#8211;list<\/span><\/p>\n<p><b>Sample application preparation<\/b><span style=\"font-weight: 400;\">: For this tutorial, we\u2019ll use a simple Node.js Express application. Create the project structure:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">mkdir my-app &amp;&amp; cd my-app<\/span><\/p>\n<p><span style=\"font-weight: 400;\">npm init -y<\/span><\/p>\n<p><span style=\"font-weight: 400;\">npm install express &#8211;save<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Create simple app.js<\/span><\/p>\n<p><span style=\"font-weight: 400;\">cat &gt; app.js &lt;&lt; &#8216;EOF&#8217;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">const express = require(&#8216;express&#8217;);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">const app = express();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">const port = process.env.PORT || 3000;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">app.get(&#8216;\/&#8217;, (req, res) =&gt; {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0res.send(&#8216;Hello from CI\/CD Pipeline v1.0!&#8217;);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">});<\/span><\/p>\n<p><span style=\"font-weight: 400;\">app.get(&#8216;\/health&#8217;, (req, res) =&gt; {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0res.status(200).json({ status: &#8216;healthy&#8217; });<\/span><\/p>\n<p><span style=\"font-weight: 400;\">});<\/span><\/p>\n<p><span style=\"font-weight: 400;\">app.listen(port, () =&gt; {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0console.log(`Server running on port ${port}`);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">});<\/span><\/p>\n<p><span style=\"font-weight: 400;\">EOF<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Create package.json start script<\/span><\/p>\n<p><span style=\"font-weight: 400;\">npm pkg set scripts.start=&#8221;node app.js&#8221;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">npm pkg set scripts.test=&#8221;echo &#8216;Running tests&#8230;&#8217; &amp;&amp; exit 0&#8243;<\/span><\/p>\n<h3><b>AWS Services Setup<\/b><\/h3>\n<p><b>Creating S3 bucket for artifacts<\/b><span style=\"font-weight: 400;\">: CodePipeline stores artifacts (build outputs, deployment packages) in S3 between stages:<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Create S3 bucket (bucket names must be globally unique)<\/span><\/p>\n<p><span style=\"font-weight: 400;\">aws s3 mb s3:\/\/my-cicd-artifacts-bucket-12345 &#8211;region us-east-1<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Enable versioning (recommended for artifact traceability)<\/span><\/p>\n<p><span style=\"font-weight: 400;\">aws s3api put-bucket-versioning \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;bucket my-cicd-artifacts-bucket-12345 \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;versioning-configuration Status=Enabled<\/span><\/p>\n<p><b>Setting up IAM roles<\/b><span style=\"font-weight: 400;\">: AWS services need IAM roles to interact with each other. Create roles for CodePipeline, CodeBuild, and CodeDeploy. These roles grant services permission to access S3 artifacts, invoke other services, and write logs.<\/span><\/p>\n<p><b>Configuring AWS credentials<\/b><span style=\"font-weight: 400;\">: For local development and testing, configure AWS credentials either through AWS CLI (<\/span><span style=\"font-weight: 400;\">aws configure<\/span><span style=\"font-weight: 400;\">) or environment variables. For production pipelines, use IAM roles attached to resources (EC2 instance profiles, ECS task roles) rather than embedding credentials.<\/span><\/p>\n<h2 id=\"scroll3\"><b>Step 1 &#8211; Setting Up Source Control with AWS CodeCommit<\/b><\/h2>\n<h3><b>Creating a CodeCommit Repository<\/b><\/h3>\n<p><b>Repository creation via AWS Console<\/b><span style=\"font-weight: 400;\">:<\/span><\/p>\n<ol>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Navigate to AWS CodeCommit in AWS Console<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Click \u201cCreate repository\u201d<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Enter repository name: <\/span><span style=\"font-weight: 400;\">my-app-repo<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Add description (optional): \u201cSample app for CI\/CD tutorial\u201d<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Click \u201cCreate\u201d<\/span><\/li>\n<\/ol>\n<p><b>Repository creation via AWS CLI<\/b><span style=\"font-weight: 400;\"> (recommended for automation):<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Create CodeCommit repository<\/span><\/p>\n<p><span style=\"font-weight: 400;\">aws codecommit create-repository \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;repository-name my-app-repo \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;repository-description &#8220;Sample application for CI\/CD pipeline&#8221; \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;region us-east-1<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Output includes cloneUrlHttp and cloneUrlSsh<\/span><\/p>\n<p><b>Cloning and initial commit<\/b><span style=\"font-weight: 400;\">:<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Clone the empty repository<\/span><\/p>\n<p><span style=\"font-weight: 400;\">git clone https:\/\/git-codecommit.us-east-1.amazonaws.com\/v1\/repos\/my-app-repo<\/span><\/p>\n<p><span style=\"font-weight: 400;\">cd my-app-repo<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Copy your application files into the repository<\/span><\/p>\n<p><span style=\"font-weight: 400;\">cp -r ..\/my-app\/* .<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Initial commit<\/span><\/p>\n<p><span style=\"font-weight: 400;\">git add .<\/span><\/p>\n<p><span style=\"font-weight: 400;\">git commit -m &#8220;Initial commit: Node.js Express application&#8221;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">git push origin main<\/span><\/p>\n<h3><b>Configuring Git Credentials<\/b><\/h3>\n<p><b>HTTPS Git credentials setup<\/b><span style=\"font-weight: 400;\">: AWS provides HTTPS Git credentials specifically for CodeCommit:<\/span><\/p>\n<ol>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Navigate to IAM Console &rarr; Users &rarr; Your User<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Security credentials tab &rarr; HTTPS Git credentials for AWS CodeCommit<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Click \u201cGenerate credentials\u201d<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Download and save username\/password<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Use these credentials when Git prompts during push\/pull operations<\/span><\/li>\n<\/ol>\n<p><b>SSH key configuration<\/b><span style=\"font-weight: 400;\"> (alternative to HTTPS):<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Generate SSH key pair<\/span><\/p>\n<p><span style=\"font-weight: 400;\">ssh-keygen -t rsa -b 4096 -C &#8220;your.email@example.com&#8221;<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Save to default location (~\/.ssh\/id_rsa)<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Display public key<\/span><\/p>\n<p><span style=\"font-weight: 400;\">cat ~\/.ssh\/id_rsa.pub<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Add public key to IAM:<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># IAM Console &rarr; Users &rarr; Your User &rarr; Security credentials &rarr;\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># SSH public keys for AWS CodeCommit &rarr; Upload SSH public key<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Configure SSH config file<\/span><\/p>\n<p><span style=\"font-weight: 400;\">cat &gt;&gt; ~\/.ssh\/config &lt;&lt; &#8216;EOF&#8217;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Host git-codecommit.*.amazonaws.com<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0User APKAEIBAERJR2EXAMPLE\u00a0 # Your SSH Key ID from IAM<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0IdentityFile ~\/.ssh\/id_rsa<\/span><\/p>\n<p><span style=\"font-weight: 400;\">EOF<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Test SSH connection<\/span><\/p>\n<p><span style=\"font-weight: 400;\">ssh git-codecommit.us-east-1.amazonaws.com<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Should return: &#8220;You have successfully authenticated&#8221;<\/span><\/p>\n<p><b>Git credential helper<\/b><span style=\"font-weight: 400;\"> (easiest for MacOS\/Linux):<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Configure Git to use AWS CLI credential helper<\/span><\/p>\n<p><span style=\"font-weight: 400;\">git config &#8211;global credential.helper &#8216;!aws codecommit credential-helper $@&#8217;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">git config &#8211;global credential.UseHttpPath true<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Now Git operations automatically use your AWS CLI credentials<\/span><\/p>\n<h3><b>Repository Best Practices<\/b><\/h3>\n<p><b>Branch protection rules<\/b><span style=\"font-weight: 400;\">: Protect critical branches from direct commits:<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># While CodeCommit doesn&#8217;t have native branch protection like GitHub,<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># use approval rule templates for pull requests<\/span><\/p>\n<p><span style=\"font-weight: 400;\">aws codecommit create-approval-rule-template \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;approval-rule-template-name &#8220;require-two-approvals&#8221; \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;approval-rule-template-description &#8220;Require 2 approvals for main branch&#8221; \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;approval-rule-template-content &#8216;{<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0&#8220;Version&#8221;: &#8220;2018-11-08&#8221;,<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0&#8220;DestinationReferences&#8221;: [&#8220;refs\/heads\/main&#8221;],<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0&#8220;Statements&#8221;: [{<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#8220;Type&#8221;: &#8220;Approvers&#8221;,<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#8220;NumberOfApprovalsNeeded&#8221;: 2<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0}]<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0}&#8217;<\/span><\/p>\n<p><b>Merge request workflows<\/b><span style=\"font-weight: 400;\">: Use pull requests for code review:<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Create feature branch<\/span><\/p>\n<p><span style=\"font-weight: 400;\">git checkout -b feature\/new-endpoint<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Make changes, commit<\/span><\/p>\n<p><span style=\"font-weight: 400;\">git add .<\/span><\/p>\n<p><span style=\"font-weight: 400;\">git commit -m &#8220;Add \/api\/status endpoint&#8221;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">git push origin feature\/new-endpoint<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Create pull request via AWS CLI<\/span><\/p>\n<p><span style=\"font-weight: 400;\">aws codecommit create-pull-request \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;title &#8220;Add status API endpoint&#8221; \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;description &#8220;Implements health check endpoint for monitoring&#8221; \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;targets repositoryName=my-app-repo,sourceReference=feature\/new-endpoint,destinationReference=main<\/span><\/p>\n<p><b>Repository triggers<\/b><span style=\"font-weight: 400;\">: Configure triggers to notify teams of repository events or trigger external systems (though CodePipeline auto-triggers are usually sufficient for CI\/CD).<\/span><\/p>\n<table>\n<tbody>\n<tr>\n<td><b>AVOID THIS MISTAKE: FORGETTING GIT CREDENTIAL CONFIGURATION<\/b><\/p>\n<p><b>What happens<\/b><span style=\"font-weight: 400;\">: You clone the repository successfully but encounter authentication errors when trying to push commits: <\/span><span style=\"font-weight: 400;\">fatal: Authentication failed for &#8216;https:\/\/git-codecommit&#8230;&#8217;<\/span><\/p>\n<p><b>Why it\u2019s problematic<\/b><span style=\"font-weight: 400;\">: CodeCommit requires specific AWS credentials; your standard AWS access keys don\u2019t work directly with Git HTTPS. Without proper credential configuration, you\u2019ll be unable to push code changes, blocking your entire CI\/CD workflow from the start.<\/span><\/p>\n<p><b>What to do instead<\/b><span style=\"font-weight: 400;\">: Configure one of three credential methods BEFORE attempting to push:<\/span><\/p>\n<ol>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Git credential helper<\/b><span style=\"font-weight: 400;\"> (recommended): <\/span><span style=\"font-weight: 400;\">git config &#8211;global credential.helper &#8216;!aws codecommit credential-helper $@&#8217;<\/span><span style=\"font-weight: 400;\"> &#8211; automatically uses AWS CLI credentials<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>HTTPS Git credentials<\/b><span style=\"font-weight: 400;\">: Generate specific Git credentials in IAM Console under Security credentials<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>SSH keys<\/b><span style=\"font-weight: 400;\">: Generate SSH key pair, upload public key to IAM, configure SSH config file<\/span><\/li>\n<\/ol>\n<p><span style=\"font-weight: 400;\">Test authentication immediately after configuration: <\/span><span style=\"font-weight: 400;\">git push origin main<\/span><span style=\"font-weight: 400;\"> should succeed without errors.<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2 id=\"scroll4\"><b>Step 2 &#8211; Configuring Build with AWS CodeBuild<\/b><\/h2>\n<h3><b>Creating a CodeBuild Project<\/b><\/h3>\n<p><b>Build environment configuration<\/b><span style=\"font-weight: 400;\">: Create a CodeBuild project defining how builds execute:<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Create CodeBuild project via AWS CLI<\/span><\/p>\n<p><span style=\"font-weight: 400;\">aws codebuild create-project \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;name my-app-build \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;source type=CODECOMMIT,location=https:\/\/git-codecommit.us-east-1.amazonaws.com\/v1\/repos\/my-app-repo \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;artifacts type=S3,location=my-cicd-artifacts-bucket-12345,packaging=ZIP,name=build-output.zip \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;environment type=LINUX_CONTAINER,image=aws\/codebuild\/standard:7.0,computeType=BUILD_GENERAL1_SMALL \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;service-role arn:aws:iam::ACCOUNT-ID:role\/CodeBuildServiceRole<\/span><\/p>\n<p><b>Docker image selection<\/b><span style=\"font-weight: 400;\">: CodeBuild uses Docker containers as build environments. AWS provides curated images (<\/span><span style=\"font-weight: 400;\">aws\/codebuild\/standard:7.0<\/span><span style=\"font-weight: 400;\"> includes Node.js, Python, Java, Docker), or use custom Docker images from ECR. Standard 7.0 includes: Node.js 18\/20, Python 3.11, Java 17, Docker, Git, AWS CLI.<\/span><\/p>\n<p><b>Compute type selection<\/b><span style=\"font-weight: 400;\">: Choose based on build requirements:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>BUILD_GENERAL1_SMALL<\/b><span style=\"font-weight: 400;\">: 3 GB memory, 2 vCPUs &#8211; $0.005\/minute (suitable for small Node.js\/Python apps)<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>BUILD_GENERAL1_MEDIUM<\/b><span style=\"font-weight: 400;\">: 7 GB memory, 4 vCPUs &#8211; $0.01\/minute (most common choice)<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>BUILD_GENERAL1_LARGE<\/b><span style=\"font-weight: 400;\">: 15 GB memory, 8 vCPUs &#8211; $0.02\/minute (large Java\/C++ projects)<\/span><\/li>\n<\/ul>\n<h3><b>Writing buildspec.yml<\/b><\/h3>\n<p><span style=\"font-weight: 400;\">The <\/span><span style=\"font-weight: 400;\">buildspec.yml<\/span><span style=\"font-weight: 400;\"> file defines build commands and must be placed in your repository root:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">version: 0.2<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Environment variables for build<\/span><\/p>\n<p><span style=\"font-weight: 400;\">env:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0variables:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0NODE_ENV: &#8220;production&#8221;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0parameter-store:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0DB_PASSWORD: \/myapp\/db\/password\u00a0 # Retrieve from Systems Manager Parameter Store<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Build phases<\/span><\/p>\n<p><span style=\"font-weight: 400;\">phases:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0install:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0runtime-versions:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0nodejs: 20<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0commands:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#8211; echo &#8220;Installing dependencies&#8230;&#8221;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#8211; npm install<\/span><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0pre_build:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0commands:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#8211; echo &#8220;Running pre-build tasks&#8230;&#8221;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#8211; echo &#8220;Build started on `date`&#8221;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#8211; npm run lint\u00a0 # Optional: linting<\/span><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0build:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0commands:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#8211; echo &#8220;Running build&#8230;&#8221;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#8211; npm run build\u00a0 # If you have a build script<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#8211; echo &#8220;Running tests&#8230;&#8221;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#8211; npm test<\/span><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0post_build:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0commands:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#8211; echo &#8220;Build completed on `date`&#8221;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#8211; echo &#8220;Packaging application&#8230;&#8221;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0# Create deployment package<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#8211; mkdir -p deployment<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#8211; cp -r node_modules deployment\/<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#8211; cp package*.json deployment\/<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#8211; cp app.js deployment\/<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#8211; cp appspec.yml deployment\/<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#8211; cp -r scripts deployment\/<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Artifacts to pass to next stage<\/span><\/p>\n<p><span style=\"font-weight: 400;\">artifacts:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0files:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0&#8211; &#8216;**\/*&#8217;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0base-directory: deployment<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0name: my-app-$(date +%Y-%m-%d-%H-%M-%S).zip<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Cache dependencies to speed up subsequent builds<\/span><\/p>\n<p><span style=\"font-weight: 400;\">cache:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0paths:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0&#8211; &#8216;node_modules\/**\/*&#8217;<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Reports for test results (optional)<\/span><\/p>\n<p><span style=\"font-weight: 400;\">reports:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0test-results:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0files:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#8211; &#8216;test-results.xml&#8217;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0file-format: &#8216;JUNITXML&#8217;<\/span><\/p>\n<p><b>Build phases explanation<\/b><span style=\"font-weight: 400;\">:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>install<\/b><span style=\"font-weight: 400;\">: Install runtime versions and dependencies<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>pre_build<\/b><span style=\"font-weight: 400;\">: Pre-build validation, linting, environment setup<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>build<\/b><span style=\"font-weight: 400;\">: Core build tasks, compilation, testing, asset generation<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>post_build<\/b><span style=\"font-weight: 400;\">: Post-build tasks\u2014packaging, artifact creation, cleanup<\/span><\/li>\n<\/ul>\n<p><b>Environment variables<\/b><span style=\"font-weight: 400;\">: Define via <\/span><span style=\"font-weight: 400;\">env.variables<\/span><span style=\"font-weight: 400;\"> (hardcoded), <\/span><span style=\"font-weight: 400;\">env.parameter-store<\/span><span style=\"font-weight: 400;\"> (Systems Manager Parameter Store for secrets), or <\/span><span style=\"font-weight: 400;\">env.secrets-manager<\/span><span style=\"font-weight: 400;\"> (Secrets Manager for sensitive data).<\/span><\/p>\n<p><b>Artifacts configuration<\/b><span style=\"font-weight: 400;\">: Specifies which files CodeBuild uploads to S3 for subsequent pipeline stages. Use <\/span><span style=\"font-weight: 400;\">base-directory<\/span><span style=\"font-weight: 400;\"> to specify root folder and <\/span><span style=\"font-weight: 400;\">files<\/span><span style=\"font-weight: 400;\"> to match patterns.<\/span><\/p>\n<h3><b>Testing the Build<\/b><\/h3>\n<p><b>Manual build execution<\/b><span style=\"font-weight: 400;\">:<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Trigger manual build<\/span><\/p>\n<p><span style=\"font-weight: 400;\">aws codebuild start-build &#8211;project-name my-app-build<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Output includes build ID<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Monitor build progress<\/span><\/p>\n<p><span style=\"font-weight: 400;\">aws codebuild batch-get-builds &#8211;ids &lt;build-id&gt;<\/span><\/p>\n<p><b>Build logs analysis<\/b><span style=\"font-weight: 400;\">: View real-time logs in CloudWatch Logs or CodeBuild Console. Look for:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Phase completion status (install, pre_build, build, post_build)<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Test results and failures<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Artifact upload confirmation<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Total build duration<\/span><\/li>\n<\/ul>\n<p><b>Troubleshooting common issues<\/b><span style=\"font-weight: 400;\">:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Dependency installation failures<\/b><span style=\"font-weight: 400;\">: Check network connectivity, verify package.json correctness<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Test failures<\/b><span style=\"font-weight: 400;\">: Review test output in logs, ensure test environment variables are set<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Artifact upload errors<\/b><span style=\"font-weight: 400;\">: Verify S3 bucket permissions, check IAM role attached to CodeBuild<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Timeout errors<\/b><span style=\"font-weight: 400;\">: Increase build timeout setting (default 60 minutes) or optimize build steps<\/span><\/li>\n<\/ul>\n<h2 id=\"scroll5\"><b>Step 3 &#8211; Configuring Deployment with AWS CodeDeploy<\/b><\/h2>\n<h3><b>Setting Up Deployment Environment<\/b><\/h3>\n<p><b>EC2 instance configuration<\/b><span style=\"font-weight: 400;\">: CodeDeploy requires target instances with the CodeDeploy agent installed:<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Launch EC2 instance (Amazon Linux 2)<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Ensure instance has IAM role with AmazonEC2RoleforAWSCodeDeploy policy<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># SSH into the instance and install the CodeDeploy agent<\/span><\/p>\n<p><span style=\"font-weight: 400;\">sudo yum update -y<\/span><\/p>\n<p><span style=\"font-weight: 400;\">sudo yum install ruby wget -y<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Download and install CodeDeploy agent<\/span><\/p>\n<p><span style=\"font-weight: 400;\">cd \/home\/ec2-user<\/span><\/p>\n<p><span style=\"font-weight: 400;\">wget https:\/\/aws-codedeploy-us-east-1.s3.us-east-1.amazonaws.com\/latest\/install<\/span><\/p>\n<p><span style=\"font-weight: 400;\">chmod +x .\/install<\/span><\/p>\n<p><span style=\"font-weight: 400;\">sudo .\/install auto<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Verify agent is running<\/span><\/p>\n<p><span style=\"font-weight: 400;\">sudo service codedeploy-agent status<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Should show: &#8220;The AWS CodeDeploy agent is running&#8221;<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Install Node.js (for our sample app)<\/span><\/p>\n<p><span style=\"font-weight: 400;\">curl -sL https:\/\/rpm.nodesource.com\/setup_20.x | sudo bash &#8211;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">sudo yum install -y nodejs<\/span><\/p>\n<p><b>CodeDeploy agent installation<\/b><span style=\"font-weight: 400;\">: The agent polls CodeDeploy for deployment instructions, downloads artifacts from S3, and executes deployment scripts specified in <\/span><span style=\"font-weight: 400;\">appspec.yml<\/span><span style=\"font-weight: 400;\">.<\/span><\/p>\n<p><b>Creating application and deployment group<\/b><span style=\"font-weight: 400;\">:<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Create CodeDeploy application<\/span><\/p>\n<p><span style=\"font-weight: 400;\">aws deploy create-application \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;application-name my-app \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;compute-platform Server<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Create deployment group (logical grouping of EC2 instances)<\/span><\/p>\n<p><span style=\"font-weight: 400;\">aws deploy create-deployment-group \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;application-name my-app \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;deployment-group-name production \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;deployment-config-name CodeDeployDefault.AllAtOnce \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;ec2-tag-filters Key=Name,Value=my-app-server,Type=KEY_AND_VALUE \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;service-role-arn arn:aws:iam::ACCOUNT-ID:role\/CodeDeployServiceRole<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Deployment groups define which instances receive deployments (via EC2 tags or Auto Scaling groups) and deployment configuration (all-at-once, one-at-a-time, half-at-a-time).<\/span><\/p>\n<h3><b>Creating appspec.yml<\/b><\/h3>\n<p><span style=\"font-weight: 400;\">The <\/span><span style=\"font-weight: 400;\">appspec.yml<\/span><span style=\"font-weight: 400;\"> file (stored in repository root) defines deployment behavior:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">version: 0.0<\/span><\/p>\n<p><span style=\"font-weight: 400;\">os: linux<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Files to copy from artifact to instance<\/span><\/p>\n<p><span style=\"font-weight: 400;\">files:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211; source: \/<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0destination: \/home\/ec2-user\/my-app<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># File permissions<\/span><\/p>\n<p><span style=\"font-weight: 400;\">permissions:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211; object: \/home\/ec2-user\/my-app<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0owner: ec2-user<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0group: ec2-user<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0mode: 755<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0type:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#8211; directory<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211; object: \/home\/ec2-user\/my-app\/app.js<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0owner: ec2-user<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0group: ec2-user<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0mode: 644<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0type:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#8211; file<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Deployment lifecycle hooks<\/span><\/p>\n<p><span style=\"font-weight: 400;\">hooks:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0# Runs before application is stopped<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0BeforeInstall:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0&#8211; location: scripts\/before_install.sh<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0timeout: 300<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0runas: root<\/span><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0# Runs after files are copied<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0AfterInstall:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0&#8211; location: scripts\/after_install.sh<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0timeout: 300<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0runas: ec2-user<\/span><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0# Runs before application starts<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0ApplicationStart:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0&#8211; location: scripts\/start_server.sh<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0timeout: 300<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0runas: ec2-user<\/span><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0# Runs after application starts (health checks)<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0ValidateService:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0&#8211; location: scripts\/validate_service.sh<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0timeout: 300<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0runas: ec2-user<\/span><\/p>\n<p><b>Deployment lifecycle hooks<\/b><span style=\"font-weight: 400;\">:<\/span><\/p>\n<ol>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>ApplicationStop<\/b><span style=\"font-weight: 400;\">: Stop currently running application<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>DownloadBundle<\/b><span style=\"font-weight: 400;\">: CodeDeploy downloads artifact from S3<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>BeforeInstall<\/b><span style=\"font-weight: 400;\">: Pre-installation tasks (stop services, backup data)<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Install<\/b><span style=\"font-weight: 400;\">: CodeDeploy copies files per <\/span><span style=\"font-weight: 400;\">files<\/span><span style=\"font-weight: 400;\"> section<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>AfterInstall<\/b><span style=\"font-weight: 400;\">: Post-installation tasks (install dependencies, configure)<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>ApplicationStart<\/b><span style=\"font-weight: 400;\">: Start the new application version<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>ValidateService<\/b><span style=\"font-weight: 400;\">: Health checks confirming successful deployment<\/span><\/li>\n<\/ol>\n<p><b>Create deployment scripts<\/b><span style=\"font-weight: 400;\"> referenced in <\/span><span style=\"font-weight: 400;\">appspec.yml<\/span><span style=\"font-weight: 400;\">:<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># scripts\/before_install.sh<\/span><\/p>\n<p><span style=\"font-weight: 400;\">#!\/bin\/bash<\/span><\/p>\n<p><span style=\"font-weight: 400;\">echo &#8220;Preparing for installation&#8230;&#8221;<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Stop existing application if running<\/span><\/p>\n<p><span style=\"font-weight: 400;\">pm2 stop my-app || true<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Clean up old deployment<\/span><\/p>\n<p><span style=\"font-weight: 400;\">rm -rf \/home\/ec2-user\/my-app<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># scripts\/after_install.sh<\/span><\/p>\n<p><span style=\"font-weight: 400;\">#!\/bin\/bash<\/span><\/p>\n<p><span style=\"font-weight: 400;\">echo &#8220;Installing dependencies&#8230;&#8221;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">cd \/home\/ec2-user\/my-app<\/span><\/p>\n<p><span style=\"font-weight: 400;\">npm install &#8211;production<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Install PM2 for process management<\/span><\/p>\n<p><span style=\"font-weight: 400;\">npm install -g pm2<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># scripts\/start_server.sh<\/span><\/p>\n<p><span style=\"font-weight: 400;\">#!\/bin\/bash<\/span><\/p>\n<p><span style=\"font-weight: 400;\">echo &#8220;Starting application&#8230;&#8221;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">cd \/home\/ec2-user\/my-app<\/span><\/p>\n<p><span style=\"font-weight: 400;\">pm2 start app.js &#8211;name my-app<\/span><\/p>\n<p><span style=\"font-weight: 400;\">pm2 save<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Configure PM2 to start on boot<\/span><\/p>\n<p><span style=\"font-weight: 400;\">pm2 startup systemd -u ec2-user &#8211;hp \/home\/ec2-user<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># scripts\/validate_service.sh<\/span><\/p>\n<p><span style=\"font-weight: 400;\">#!\/bin\/bash<\/span><\/p>\n<p><span style=\"font-weight: 400;\">echo &#8220;Validating deployment&#8230;&#8221;<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Wait for application to start<\/span><\/p>\n<p><span style=\"font-weight: 400;\">sleep 10<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Check if process is running<\/span><\/p>\n<p><span style=\"font-weight: 400;\">if pm2 list | grep -q &#8220;my-app&#8221;; then<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0echo &#8220;Application is running&#8221;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0# Test health endpoint<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0response=$(curl -s -o \/dev\/null -w &#8220;%{http_code}&#8221; http:\/\/localhost:3000\/health)<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0if [ &#8220;$response&#8221; = &#8220;200&#8221; ]; then<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0echo &#8220;Health check passed&#8221;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0exit 0<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0else<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0echo &#8220;Health check failed&#8221;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0exit 1<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0fi<\/span><\/p>\n<p><span style=\"font-weight: 400;\">else<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0echo &#8220;Application failed to start&#8221;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0exit 1<\/span><\/p>\n<p><span style=\"font-weight: 400;\">fi<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Make scripts executable: <\/span><span style=\"font-weight: 400;\">chmod +x scripts\/*.sh<\/span><\/p>\n<h3><b>Deployment Strategies<\/b><\/h3>\n<p><b>In-place deployment<\/b><span style=\"font-weight: 400;\">: Stops the application on current instances, deploys the new version, and restarts the application. Causes brief downtime but requires no additional infrastructure.<\/span><\/p>\n<p><b>Blue\/green deployment<\/b><span style=\"font-weight: 400;\">: Creates a new set of instances (green), deploys to green, routes traffic from old instances (blue) to green, then terminates blue. Enables zero-downtime deployments and instant rollback but requires double the infrastructure temporarily.<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Create blue\/green deployment group<\/span><\/p>\n<p><span style=\"font-weight: 400;\">aws deploy create-deployment-group \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;application-name my-app \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;deployment-group-name production-blue-green \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;deployment-style deploymentType=BLUE_GREEN,deploymentOption=WITH_TRAFFIC_CONTROL \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;blue-green-deployment-configuration \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0terminateBlueInstancesOnDeploymentSuccess={action=TERMINATE,terminationWaitTimeInMinutes=5},\\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0deploymentReadyOption={actionOnTimeout=CONTINUE_DEPLOYMENT},\\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0greenFleetProvisioningOption={action=COPY_AUTO_SCALING_GROUP}<\/span><\/p>\n<p><b>Deployment configuration options<\/b><span style=\"font-weight: 400;\">:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>CodeDeployDefault.AllAtOnce<\/b><span style=\"font-weight: 400;\">: Deploy to all instances simultaneously (fastest, most risk)<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>CodeDeployDefault.OneAtATime<\/b><span style=\"font-weight: 400;\">: Deploy to one instance at a time (slowest, least risk)<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>CodeDeployDefault.HalfAtATime<\/b><span style=\"font-weight: 400;\">: Deploy to 50% of instances at a time (balance)<\/span><\/li>\n<\/ul>\n<h2 id=\"scroll6\"><b>Step 4 &#8211; Creating the Complete Pipeline with AWS CodePipeline<\/b><\/h2>\n<h3><b>Pipeline Creation<\/b><\/h3>\n<p><b>AWS Console approach<\/b><span style=\"font-weight: 400;\">:<\/span><\/p>\n<ol>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Navigate to CodePipeline &rarr; Create pipeline<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Pipeline name: <\/span><span style=\"font-weight: 400;\">my-app-pipeline<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Service role: Create new role (auto-generates necessary permissions)<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Artifact store: Choose the S3 bucket created earlier<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Click \u201cNext\u201d<\/span><\/li>\n<\/ol>\n<p><b>Source stage configuration<\/b><span style=\"font-weight: 400;\">:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Source provider: AWS CodeCommit<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Repository name: <\/span><span style=\"font-weight: 400;\">my-app-repo<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Branch name: <\/span><span style=\"font-weight: 400;\">main<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Detection option: CloudWatch Events (recommended) or AWS CodePipeline (polling)<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Output artifacts: <\/span><span style=\"font-weight: 400;\">SourceArtifact<\/span><\/li>\n<\/ul>\n<p><b>Build stage integration<\/b><span style=\"font-weight: 400;\">:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Build provider: AWS CodeBuild<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Region: Same as pipeline<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Project name: <\/span><span style=\"font-weight: 400;\">my-app-build<\/span><span style=\"font-weight: 400;\"> (created earlier)<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Input artifacts: <\/span><span style=\"font-weight: 400;\">SourceArtifact<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Output artifacts: <\/span><span style=\"font-weight: 400;\">BuildArtifact<\/span><\/li>\n<\/ul>\n<p><b>Deploy stage setup<\/b><span style=\"font-weight: 400;\">:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Deploy provider: AWS CodeDeploy<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Region: Same as pipeline<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Application name: <\/span><span style=\"font-weight: 400;\">my-app<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Deployment group: <\/span><span style=\"font-weight: 400;\">production<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Input artifacts: <\/span><span style=\"font-weight: 400;\">BuildArtifact<\/span><\/li>\n<\/ul>\n<p><span style=\"font-weight: 400;\">Click \u201cCreate pipeline\u201d and the pipeline immediately executes.<\/span><\/p>\n<p><img class=\"aligncenter wp-image-27052 size-full\" title=\"Pipeline Stage vs AWS Services vs Files\" src=\"https:\/\/www.invensislearning.com\/blog\/wp-content\/uploads\/2026\/01\/pipeline-stage-vs-aws-services-vs-files.jpg\" alt=\"Pipeline Stage vs AWS Services vs Files\" width=\"1000\" height=\"691\" srcset=\"https:\/\/www.invensislearning.com\/blog\/wp-content\/uploads\/2026\/01\/pipeline-stage-vs-aws-services-vs-files.jpg 1000w, https:\/\/www.invensislearning.com\/blog\/wp-content\/uploads\/2026\/01\/pipeline-stage-vs-aws-services-vs-files-300x207.jpg 300w, https:\/\/www.invensislearning.com\/blog\/wp-content\/uploads\/2026\/01\/pipeline-stage-vs-aws-services-vs-files-768x531.jpg 768w, https:\/\/www.invensislearning.com\/blog\/wp-content\/uploads\/2026\/01\/pipeline-stage-vs-aws-services-vs-files-218x150.jpg 218w, https:\/\/www.invensislearning.com\/blog\/wp-content\/uploads\/2026\/01\/pipeline-stage-vs-aws-services-vs-files-696x481.jpg 696w, https:\/\/www.invensislearning.com\/blog\/wp-content\/uploads\/2026\/01\/pipeline-stage-vs-aws-services-vs-files-608x420.jpg 608w, https:\/\/www.invensislearning.com\/blog\/wp-content\/uploads\/2026\/01\/pipeline-stage-vs-aws-services-vs-files-100x70.jpg 100w\" sizes=\"(max-width: 1000px) 100vw, 1000px\" \/><\/p>\n<p><b>CloudFormation template for complete pipeline<\/b><span style=\"font-weight: 400;\"> (infrastructure as code approach):<\/span><\/p>\n<p><span style=\"font-weight: 400;\">AWSTemplateFormatVersion: &#8216;2010-09-09&#8217;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Description: &#8216;Complete CI\/CD Pipeline for sample application&#8217;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Parameters:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0RepositoryName:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0Type: String<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0Default: my-app-repo<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0BranchName:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0Type: String<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0Default: main<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Resources:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0# S3 Bucket for artifacts<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0ArtifactBucket:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0Type: AWS::S3::Bucket<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0Properties:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0VersioningConfiguration:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Status: Enabled<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0BucketEncryption:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ServerSideEncryptionConfiguration:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#8211; ServerSideEncryptionByDefault:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0SSEAlgorithm: AES256<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0# CodePipeline<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0AppPipeline:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0Type: AWS::CodePipeline::Pipeline<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0Properties:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Name: my-app-pipeline<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0RoleArn: !GetAtt CodePipelineServiceRole.Arn<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ArtifactStore:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Type: S3<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Location: !Ref ArtifactBucket<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Stages:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0# Source Stage<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#8211; Name: Source<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Actions:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#8211; Name: SourceAction<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ActionTypeId:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Category: Source<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Owner: AWS<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Provider: CodeCommit<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Version: &#8216;1&#8217;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Configuration:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0RepositoryName: !Ref RepositoryName<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0BranchName: !Ref BranchName<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0PollForSourceChanges: false<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0OutputArtifacts:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#8211; Name: SourceOutput<\/span><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0# Build Stage<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#8211; Name: Build<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Actions:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#8211; Name: BuildAction<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ActionTypeId:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Category: Build<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Owner: AWS<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Provider: CodeBuild<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Version: &#8216;1&#8217;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Configuration:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ProjectName: !Ref CodeBuildProject<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0InputArtifacts:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#8211; Name: SourceOutput<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0OutputArtifacts:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#8211; Name: BuildOutput<\/span><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0# Deploy Stage<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#8211; Name: Deploy<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Actions:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#8211; Name: DeployAction<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ActionTypeId:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Category: Deploy<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Owner: AWS<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Provider: CodeDeploy<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Version: &#8216;1&#8217;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Configuration:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ApplicationName: my-app<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0DeploymentGroupName: production<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0InputArtifacts:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#8211; Name: BuildOutput<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0# IAM Roles (simplified &#8211; expand with least privilege policies)<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0CodePipelineServiceRole:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0Type: AWS::IAM::Role<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0Properties:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0AssumeRolePolicyDocument:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Version: &#8216;2012-10-17&#8217;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Statement:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#8211; Effect: Allow<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Principal:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Service: codepipeline.amazonaws.com<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Action: sts:AssumeRole<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ManagedPolicyArns:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#8211; arn:aws:iam::aws:policy\/AWSCodePipelineFullAccess<\/span><\/p>\n<h3><b>Adding Manual Approval Stage<\/b><\/h3>\n<p><span style=\"font-weight: 400;\">Manual approval adds human gate before production deployment:<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Add between Build and Deploy stages in CloudFormation template<\/span><\/p>\n<p><span style=\"font-weight: 400;\">&#8211; Name: Approval<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0Actions:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0&#8211; Name: ManualApproval<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ActionTypeId:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Category: Approval<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Owner: AWS<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Provider: Manual<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Version: &#8216;1&#8217;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Configuration:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0NotificationArn: !Ref ApprovalSNSTopic<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0CustomData: &#8216;Please review build artifacts and approve production deployment&#8217;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ExternalEntityLink: !Sub &#8216;https:\/\/console.aws.amazon.com\/codebuild\/home?region=${AWS::Region}#\/projects\/${CodeBuildProject}\/history&#8217;<\/span><\/p>\n<p><b>SNS notification setup<\/b><span style=\"font-weight: 400;\"> for approval notifications:<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Create SNS topic for approvals<\/span><\/p>\n<p><span style=\"font-weight: 400;\">aws sns create-topic &#8211;name pipeline-approvals<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Subscribe email to topic<\/span><\/p>\n<p><span style=\"font-weight: 400;\">aws sns subscribe \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;topic-arn arn:aws:sns:us-east-1:ACCOUNT-ID:pipeline-approvals \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;protocol email \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;notification-endpoint your.email@example.com<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Confirm subscription via email link<\/span><\/p>\n<p><span style=\"font-weight: 400;\">When pipeline reaches approval stage, designated approvers receive SNS email notification with link to approve or reject deployment.<\/span><\/p>\n<h3><b>Pipeline Execution and Monitoring<\/b><\/h3>\n<p><b>Triggering pipeline runs<\/b><span style=\"font-weight: 400;\">: Pipelines automatically trigger on source changes (if CloudWatch Events enabled):<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Manual pipeline execution<\/span><\/p>\n<p><span style=\"font-weight: 400;\">aws codepipeline start-pipeline-execution &#8211;name my-app-pipeline<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># View pipeline state<\/span><\/p>\n<p><span style=\"font-weight: 400;\">aws codepipeline get-pipeline-state &#8211;name my-app-pipeline<\/span><\/p>\n<p><b>Viewing execution history<\/b><span style=\"font-weight: 400;\">: CodePipeline Console shows:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Execution history with timestamps<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Stage status (In Progress, Succeeded, Failed)<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Action details and logs<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Execution duration<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Who triggered execution (Git commit author, manual trigger)<\/span><\/li>\n<\/ul>\n<p><b>Stage-level monitoring<\/b><span style=\"font-weight: 400;\">: Click individual stages to view:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Action details and configuration<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Input\/output artifacts<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">CloudWatch logs links<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Error messages (if failed)<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Retry options<\/span><\/li>\n<\/ul>\n<h2 id=\"scroll7\"><b>Advanced Configurations and Best Practices<\/b><\/h2>\n<h3><b>Environment Variables and Secrets Management<\/b><\/h3>\n<p><b>AWS Systems Manager Parameter Store<\/b><span style=\"font-weight: 400;\">: Store non-sensitive configuration as parameters:<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Store parameter<\/span><\/p>\n<p><span style=\"font-weight: 400;\">aws ssm put-parameter \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;name \/myapp\/prod\/api-url \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;value &#8220;https:\/\/api.example.com&#8221; \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;type String<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Reference in buildspec.yml<\/span><\/p>\n<p><span style=\"font-weight: 400;\">env:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0parameter-store:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0API_URL: \/myapp\/prod\/api-url<\/span><\/p>\n<p><b>AWS Secrets Manager integration<\/b><span style=\"font-weight: 400;\">: Store sensitive data (passwords, API keys):<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Create secret<\/span><\/p>\n<p><span style=\"font-weight: 400;\">aws secretsmanager create-secret \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;name myapp\/db\/credentials \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;secret-string &#8216;{&#8220;username&#8221;:&#8221;admin&#8221;,&#8221;password&#8221;:&#8221;MySecureP@ssw0rd&#8221;}&#8217;<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Reference in buildspec.yml<\/span><\/p>\n<p><span style=\"font-weight: 400;\">env:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0secrets-manager:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0DB_USERNAME: myapp\/db\/credentials:username<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0DB_PASSWORD: myapp\/db\/credentials:password<\/span><\/p>\n<p><b>Environment-specific configurations<\/b><span style=\"font-weight: 400;\">: Maintain separate parameters\/secrets for dev, staging, production using naming conventions (<\/span><span style=\"font-weight: 400;\">\/myapp\/{env}\/config<\/span><span style=\"font-weight: 400;\">) and reference appropriate environment in pipeline.<\/span><\/p>\n<h3><b>Pipeline Optimization<\/b><\/h3>\n<p><b>Parallel execution stages<\/b><span style=\"font-weight: 400;\">: Run independent stages concurrently to reduce pipeline duration:<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Multiple actions in same stage execute in parallel<\/span><\/p>\n<p><span style=\"font-weight: 400;\">&#8211; Name: Test<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0Actions:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0&#8211; Name: UnitTests<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ActionTypeId:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Category: Test<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Owner: AWS<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Provider: CodeBuild<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Configuration:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ProjectName: my-app-unit-tests<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0&#8211; Name: IntegrationTests<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ActionTypeId:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Category: Test<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Owner: AWS<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Provider: CodeBuild<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Configuration:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ProjectName: my-app-integration-tests<\/span><\/p>\n<p><b>Caching strategies<\/b><span style=\"font-weight: 400;\">: Cache dependencies between builds to reduce build time and costs:<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># In buildspec.yml<\/span><\/p>\n<p><span style=\"font-weight: 400;\">cache:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0paths:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0&#8211; &#8216;node_modules\/**\/*&#8217; \u00a0 \u00a0 # NPM dependencies<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0&#8211; &#8216;.m2\/**\/*&#8217;\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 # Maven dependencies<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0&#8211; &#8216;.gradle\/**\/*&#8217;\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 # Gradle dependencies<\/span><\/p>\n<p><span style=\"font-weight: 400;\">First build downloads all dependencies (slow), subsequent builds retrieve from cache (fast\u201460-80% faster install phase).<\/span><\/p>\n<p><b>Build time optimization<\/b><span style=\"font-weight: 400;\">:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Use smaller Docker base images (reduce pull time)<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Implement layer caching for Docker builds<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Run tests in parallel where possible<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Skip unnecessary build steps for non-code changes (documentation-only commits)<\/span><\/li>\n<\/ul>\n<h3><b>Security Best Practices<\/b><\/h3>\n<p><b>Least privilege IAM policies<\/b><span style=\"font-weight: 400;\">: Grant minimum permissions required:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">{<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8220;Version&#8221;: &#8220;2012-10-17&#8221;,<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8220;Statement&#8221;: [<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0{<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#8220;Effect&#8221;: &#8220;Allow&#8221;,<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#8220;Action&#8221;: [<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#8220;codecommit:GitPull&#8221;,<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#8220;codecommit:UploadArchive&#8221;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0],<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#8220;Resource&#8221;: &#8220;arn:aws:codecommit:us-east-1:ACCOUNT-ID:my-app-repo&#8221;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0]<\/span><\/p>\n<p><span style=\"font-weight: 400;\">}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Instead of <\/span><span style=\"font-weight: 400;\">AWSCodeCommitFullAccess<\/span><span style=\"font-weight: 400;\"> (overly broad), create policies scoped to specific repositories and actions.<\/span><\/p>\n<p><b>Encryption at rest and in transit<\/b><span style=\"font-weight: 400;\">: Enable encryption for S3 artifact buckets (AES-256 or KMS), CodeCommit repositories (automatic), and CodeBuild environment variables (automatic for Parameter Store\/Secrets Manager).<\/span><\/p>\n<p><b>Vulnerability scanning integration<\/b><span style=\"font-weight: 400;\">: Add security scanning to build stage:<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># In buildspec.yml post_build phase<\/span><\/p>\n<p><span style=\"font-weight: 400;\">post_build:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0commands:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0# Dependency vulnerability scanning<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0&#8211; npm audit &#8211;audit-level=high<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0# Container image scanning (if using Docker)<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0&#8211; trivy image my-app: latest &#8211;severity HIGH, CRITICAL<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Configure builds to fail if high\/critical vulnerabilities are detected, preventing vulnerable code from deploying.<\/span><\/p>\n<table>\n<tbody>\n<tr>\n<td><b>PRO TIP: PERFORMANCE OPTIMIZATION<\/b><\/p>\n<p><b>Enable caching in CodeBuild to reduce build times by 60-80% and cut costs proportionally.<\/b><span style=\"font-weight: 400;\"> The first build after enabling caching will be slow (downloading all dependencies), but subsequent builds retrieve dependencies from the cache instead of downloading fresh. For a Node.js app with 200 dependencies, this reduces the install phase from 3 minutes to 30 seconds.<\/span><\/p>\n<p><b>Optimize cache configuration<\/b><span style=\"font-weight: 400;\">: Cache only immutable dependencies (node_modules, not source code), use cache hit\/miss metrics to verify caching effectiveness, and periodically clear cache (weekly) to prevent stale dependency issues. In buildspec.yml cache section, specify paths precisely\u2014don\u2019t cache entire working directories or you\u2019ll negate benefits and increase cache size\/cost.<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2 id=\"scroll8\"><b>Monitoring, Logging, and Troubleshooting<\/b><\/h2>\n<h3><b>CloudWatch Integration<\/b><\/h3>\n<p><b>Pipeline metrics<\/b><span style=\"font-weight: 400;\">: CodePipeline automatically publishes metrics to CloudWatch:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">PipelineExecutionSuccess<\/span><span style=\"font-weight: 400;\"> \/ <\/span><span style=\"font-weight: 400;\">PipelineExecutionFailure<\/span><span style=\"font-weight: 400;\"> counts<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">PipelineExecutionTime<\/span><span style=\"font-weight: 400;\"> for performance tracking<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">StageExecutionTime<\/span><span style=\"font-weight: 400;\"> identifies bottleneck stages<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">ActionExecutionTime<\/span><span style=\"font-weight: 400;\"> for individual action performance<\/span><\/li>\n<\/ul>\n<p><span style=\"font-weight: 400;\">Create CloudWatch dashboards visualizing these metrics for pipeline health monitoring.<\/span><\/p>\n<p><b>Log aggregation<\/b><span style=\"font-weight: 400;\">: All services write logs to CloudWatch Logs:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>CodeBuild<\/b><span style=\"font-weight: 400;\">: <\/span><span style=\"font-weight: 400;\">\/aws\/codebuild\/{project-name}<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>CodeDeploy<\/b><span style=\"font-weight: 400;\">: <\/span><span style=\"font-weight: 400;\">\/aws\/codedeploy\/{application-name}<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Lambda (if using)<\/b><span style=\"font-weight: 400;\">: <\/span><span style=\"font-weight: 400;\">\/aws\/lambda\/{function-name}<\/span><\/li>\n<\/ul>\n<p><span style=\"font-weight: 400;\">Query logs using CloudWatch Logs Insights for troubleshooting:<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Find all build failures in last 24 hours<\/span><\/p>\n<p><span style=\"font-weight: 400;\">fields @timestamp, @message<\/span><\/p>\n<p><span style=\"font-weight: 400;\">| filter @message like \/ERROR\/<\/span><\/p>\n<p><span style=\"font-weight: 400;\">| sort @timestamp desc<\/span><\/p>\n<p><span style=\"font-weight: 400;\">| limit 20<\/span><\/p>\n<p><b>Alerting setup<\/b><span style=\"font-weight: 400;\">: Create CloudWatch Alarms for critical events:<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Alert on pipeline failures<\/span><\/p>\n<p><span style=\"font-weight: 400;\">aws cloudwatch put-metric-alarm \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;alarm-name pipeline-failure-alert \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;alarm-description &#8220;Alert when pipeline fails&#8221; \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;metric-name PipelineExecutionFailure \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;namespace AWS\/CodePipeline \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;statistic Sum \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;period 300 \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;evaluation-periods 1 \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;threshold 1 \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;comparison-operator GreaterThanOrEqualToThreshold \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;alarm-actions arn:aws:sns:us-east-1:ACCOUNT-ID:devops-alerts<\/span><\/p>\n<h3><b>Common Issues and Solutions<\/b><\/h3>\n<p><b>Build failures<\/b><span style=\"font-weight: 400;\">:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Symptom<\/b><span style=\"font-weight: 400;\">: CodeBuild reports <\/span><span style=\"font-weight: 400;\">FAILED<\/span><span style=\"font-weight: 400;\"> status<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Common causes<\/b><span style=\"font-weight: 400;\">: Dependency installation errors, test failures, buildspec.yml syntax errors, insufficient permissions<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Solution<\/b><span style=\"font-weight: 400;\">: Review CloudWatch Logs for build, identify failing command, fix locally and test, commit fix<\/span><\/li>\n<\/ul>\n<p><b>Deployment errors<\/b><span style=\"font-weight: 400;\">:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Symptom<\/b><span style=\"font-weight: 400;\">: CodeDeploy reports <\/span><span style=\"font-weight: 400;\">FAILED<\/span><span style=\"font-weight: 400;\"> status<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Common causes<\/b><span style=\"font-weight: 400;\">: CodeDeploy agent not running, appspec.yml script errors, insufficient disk space, validation hook failures<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Solution<\/b><span style=\"font-weight: 400;\">: SSH to EC2 instance, check CodeDeploy agent status (<\/span><span style=\"font-weight: 400;\">sudo service codedeploy-agent status<\/span><span style=\"font-weight: 400;\">), review deployment logs (<\/span><span style=\"font-weight: 400;\">\/var\/log\/aws\/codedeploy-agent\/<\/span><span style=\"font-weight: 400;\">), manually test deployment scripts<\/span><\/li>\n<\/ul>\n<p><b>Permission issues<\/b><span style=\"font-weight: 400;\">:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Symptom<\/b><span style=\"font-weight: 400;\">: <\/span><span style=\"font-weight: 400;\">AccessDenied<\/span><span style=\"font-weight: 400;\"> errors in logs<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Common causes<\/b><span style=\"font-weight: 400;\">: Missing IAM permissions, incorrect service role ARN, cross-account permission gaps<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Solution<\/b><span style=\"font-weight: 400;\">: Review IAM role policies, add missing permissions, verify role trust relationships, test with IAM Policy Simulator<\/span><\/li>\n<\/ul>\n<h3><b>Debugging Strategies<\/b><\/h3>\n<p><b>CloudWatch Logs analysis<\/b><span style=\"font-weight: 400;\">: Enable verbose logging in buildspec.yml for detailed output:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">phases:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0build:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0commands:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#8211; set -x\u00a0 # Enable bash debug mode (prints each command)<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#8211; npm run build 2&gt;&amp;1 | tee build.log\u00a0 # Capture output<\/span><\/p>\n<p><b>CodeBuild debug sessions<\/b><span style=\"font-weight: 400;\">: For complex build issues, use the CodeBuild session manager to interactively debug:<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Start build with session manager enabled<\/span><\/p>\n<p><span style=\"font-weight: 400;\">aws codebuild start-build \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;project-name my-app-build \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;session-enabled \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;debug-session-enabled<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Connect to build container (requires Session Manager plugin)<\/span><\/p>\n<p><span style=\"font-weight: 400;\">aws codebuild start-build-batch \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8211;project-name my-app-build<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># SSH into build environment<\/span><\/p>\n<p><span style=\"font-weight: 400;\">aws codebuild start-session &#8211;build-id &lt;build-id&gt;<\/span><\/p>\n<p><b>CodeDeploy troubleshooting<\/b><span style=\"font-weight: 400;\">: Most deployment issues relate to scripts or permissions:<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># View deployment logs on EC2 instance<\/span><\/p>\n<p><span style=\"font-weight: 400;\">sudo tail -f \/var\/log\/aws\/codedeploy-agent\/codedeploy-agent.log<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Check deployment directory<\/span><\/p>\n<p><span style=\"font-weight: 400;\">ls -la \/opt\/codedeploy-agent\/deployment-root\/<\/span><\/p>\n<p><span style=\"font-weight: 400;\"># Manually test deployment scripts<\/span><\/p>\n<p><span style=\"font-weight: 400;\">cd \/home\/ec2-user\/my-app\/scripts<\/span><\/p>\n<p><span style=\"font-weight: 400;\">bash -x start_server.sh\u00a0 # Run with debug output<\/span><\/p>\n<h2 id=\"scroll9\"><b>Conclusion<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">A well-designed CI\/CD pipeline on AWS transforms deployments from fragile, manual processes into a repeatable, automated system that delivers reliable changes quickly. Using CodeCommit, CodeBuild, CodeDeploy, and CodePipeline together gives you a fully managed, cloud-native delivery flow that scales with your applications and teams.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Start by implementing a basic pipeline for a single service, get it stable, then extend it with blue\/green deployments, automated tests, security scans, and promotion across dev\u2013staging, prod. As your maturity grows, standardize these patterns across all critical applications so every change follows the same proven path to production.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">If you want to go beyond \u201cfollowing tutorials\u201d and actually design robust AWS delivery pipelines end-to-end, consider Invensis Learning\u2019s<\/span> <a href=\"https:\/\/www.invensislearning.com\/aws-devops-training-course\/\" target=\"_blank\" rel=\"noopener\">AWS DevOps Certification<span style=\"font-weight: 400;\"> training<\/span><\/a><span style=\"font-weight: 400;\">. It helps you align AWS tooling with DevOps principles, so your CI\/CD pipeline becomes a core business capability rather than a one-off setup.<\/span><\/p>\n<h2 id=\"scroll10\"><b>Frequently Asked Questions<\/b><\/h2>\n<h3><strong>1. Do I need to use all AWS native services, or can I integrate third-party tools?<\/strong><\/h3>\n<p><span style=\"font-weight: 400;\">AWS CodePipeline integrates seamlessly with third-party tools, enabling incremental adoption. Common hybrid patterns: use GitHub\/GitLab for source control (developers prefer existing workflows) but CodeBuild\/CodeDeploy for AWS-specific build and deployment tasks; use Jenkins for builds (leveraging existing Jenkins expertise and plugins) but CodeDeploy for AWS deployments; or use AWS native services for new projects while maintaining existing Jenkins\/GitLab CI pipelines for legacy applications. CodePipeline\u2019s integration flexibility lets you start where you are and migrate gradually rather than forcing a complete replacement.<\/span><\/p>\n<h3><b>2. How much does running a CI\/CD pipeline on AWS cost?<\/b><\/h3>\n<p><span style=\"font-weight: 400;\">Costs depend on usage volume but are generally modest for small-to-medium teams: <\/span><b>CodePipeline<\/b><span style=\"font-weight: 400;\">: $1\/active pipeline\/month (first pipeline free); <\/span><b>CodeBuild<\/b><span style=\"font-weight: 400;\">: ~$0.005\/minute for small compute ($0.30\/hour), typical build taking 5 minutes costs $0.025;\u00a0<\/span><\/p>\n<p><b>CodeDeploy<\/b><span style=\"font-weight: 400;\">: Free for EC2\/on-premise deployments, $0.02 per on-demand code deployment for Lambda\/ECS; <\/span><b>CodeCommit<\/b><span style=\"font-weight: 400;\">: $1\/active user\/month (5 users free), $0.06\/GB-month storage; <\/span><b>S3 artifact storage<\/b><span style=\"font-weight: 400;\">: $0.023\/GB-month. <\/span><b>Example cost<\/b><span style=\"font-weight: 400;\"> for a small team (5 developers, 100 builds\/month, 50 deployments\/month): ~$5-15\/month total, much cheaper than managing Jenkins servers (~$200-500\/month for EC2 instances and maintenance).<\/span><\/p>\n<h3><b>3. How do I implement CI\/CD for Lambda functions or containers instead of EC2?<\/b><\/h3>\n<p><b>For Lambda<\/b><span style=\"font-weight: 400;\">: Use CodeBuild to package Lambda code (zip or container image), use CodeDeploy with da eployment configuration supporting Lambda (traffic shifting, canary deployments), and update the Lambda function in deploy stage.\u00a0<\/span><\/p>\n<p><b>For containers (ECS\/EKS)<\/b><span style=\"font-weight: 400;\">: Use CodeBuild to build Docker images (<\/span><span style=\"font-weight: 400;\">docker build<\/span><span style=\"font-weight: 400;\">, push to ECR), use CodeDeploy for ECS services (supports blue\/green deployments with automatic traffic shifting), or use kubectl\/Helm commands in CodeBuild for Kubernetes deployments. CodePipeline supports all compute platforms, adjusts build and deploy stages based on target platform while maintaining same overall pipeline structure.<\/span><\/p>\n<h3><b>4. How do I set up separate pipelines for dev, staging, and production environments?<\/b><\/h3>\n<p><b>Option 1 &#8211; Separate pipelines<\/b><span style=\"font-weight: 400;\">: Create distinct pipelines per environment (dev-pipeline, staging-pipeline, prod-pipeline) triggered by different branches (develop &rarr; dev-pipeline, main &rarr; prod-pipeline). Provides isolation but duplicates configuration.\u00a0<\/span><\/p>\n<p><b>Option 2 &#8211; Multi-stage single pipeline:<\/b><span style=\"font-weight: 400;\"> (recommended): Create one pipeline with stages for each environment: Source &rarr; Build &rarr; Deploy-to-Dev &rarr; Manual-Approval &rarr; Deploy-to-Staging &rarr; Manual-Approval &rarr; Deploy-to-Production. Each deploy stage uses different CodeDeploy deployment groups targeting different EC2 instances\/environments. Use environment-specific parameters from Parameter Store (e.g., <\/span><span style=\"font-weight: 400;\">\/myapp\/dev\/db-url<\/span><span style=\"font-weight: 400;\">, <\/span><span style=\"font-weight: 400;\">\/myapp\/prod\/db-url<\/span><span style=\"font-weight: 400;\">) referenced in deployment configurations.<\/span><\/p>\n<h3><b>5. What happens if a deployment fails halfway through? How do I rollback?<\/b><\/h3>\n<p><span style=\"font-weight: 400;\">CodeDeploy automatically handles rollback if deployment fails during execution: if the ValidateService hook fails or instances become unhealthy during deployment, CodeDeploy marks the deployment as FAILED and can automatically rollback to previous version (if <\/span><span style=\"font-weight: 400;\">AutoRollbackConfiguration<\/span><span style=\"font-weight: 400;\"> enabled). For deployments that succeed but later prove problematic: use CodeDeploy Console \u201cRedeploy previous revision\u201d to instantly deploy previous working version, or trigger pipeline with the previous Git commit SHA.\u00a0<\/span><\/p>\n<p><b>Best practice<\/b><span style=\"font-weight: 400;\">: Enable automatic rollback in CodeDeploy deployment groups, implement comprehensive ValidateService hooks catching issues during deployment rather than after, and maintain deployment history enabling easy identification of the last known good version.<\/span><\/p>\n<h3><b>6. How do I run integration tests or database migrations as part of the pipeline?<\/b><\/h3>\n<p><b>Integration tests<\/b><span style=\"font-weight: 400;\">: Add Test stage between the Build and Deploy stages using CodeBuild project that runs integration tests against deployed staging environment. Configure the test project to pull artifacts from Build stage, deploy to the temporary test environment, execute integration tests, report results (pass\/fail), and tear down the test environment.\u00a0<\/span><\/p>\n<p><b>Database migrations<\/b><span style=\"font-weight: 400;\">: Include migration scripts in the deployment package. Add migration execution to appspec.yml in the BeforeInstall or AfterInstall hooks (runs on one instance using a mutex\/lock to prevent concurrent execution). Verify migrations succeeded in the ValidateService hook before proceeding. For zero-downtime requirements, use backward-compatible migrations (add columns, deploy code, remove old columns later) supporting old and new code versions simultaneously.<\/span><\/p>\n<h3><b>7. Can I use CodePipeline to deploy infrastructure changes (Infrastructure as Code)?<\/b><\/h3>\n<p><span style=\"font-weight: 400;\">Yes, CodePipeline commonly deploys infrastructure using CloudFormation, Terraform, or CDK:\u00a0<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>CloudFormation approach<\/b><span style=\"font-weight: 400;\">: Add Deploy stage with CloudFormation action type, specify template file from source stage, use parameter overrides for environment-specific values, and CloudFormation creates\/updates stack.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Terraform approach<\/b><span style=\"font-weight: 400;\">: Use CodeBuild project executing Terraform commands (<\/span><span style=\"font-weight: 400;\">terraform plan<\/span><span style=\"font-weight: 400;\">, <\/span><span style=\"font-weight: 400;\">terraform apply<\/span><span style=\"font-weight: 400;\">), store Terraform state in S3 backend with DynamoDB locking, use separate pipeline stages for plan (review changes) and apply (execute changes).<\/span><\/li>\n<\/ul>\n<p><b>Best practice<\/b><span style=\"font-weight: 400;\">: Separate infrastructure pipelines from application pipelines unless tightly coupled, use manual approval before infrastructure changes in production (infrastructure changes higher risk than application deployments), and implement drift detection monitoring infrastructure state versus code.<\/span><\/p>\n<p><span style=\"font-weight: 400;\"><div class='white' style='background:rgba(0,0,0,0); border:solid 0px rgba(0, 0, 0, 0); border-radius:0px; padding:0px 0px 0px 0px;'>\n<div id='sample_slider' class='owl-carousel sa_owl_theme owl-pagination-true autohide-arrows' data-slider-id='sample_slider' style='visibility:hidden;'>\n<div id='sample_slider_slide02' class='sa_hover_container' style='padding:0% 2%; margin:0px 0%; '><div style=\"text-align: center;\r\n \r\n    opacity: 1;\r\n    background-repeat: no-repeat;\r\n    background-size: cover;;\"  class=\"test-shine\">\r\n<a href=\"https:\/\/www.invensislearning.com\/devops-master-certification-training\/\" rel=\"bookmark\" title=\"DevOps Master Certification Training\" style=\"color:#fff\">\r\n\r\n<div class=\"td-module-meta-info SlideBox\" style=\"background:linear-gradient(0deg,#5EBDAE,#C1EA9E 100%,rgba(0,0,0,0));text-align:center;padding:30px\">\r\n\r\n<div class=\"tdb-module-title-wrap\"><p class=\"entry-title td-module-title\" style=\"    color: #fff;\r\n    font-size: 18px !important;\r\n    margin: 36px auto;\">\r\nDevOps Master Certification Training\r\n<\/p><\/div>\r\n<\/div>\r\n<\/a>\r\n<\/div><\/div>\n<div id='sample_slider_slide03' class='sa_hover_container' style='padding:0% 2%; margin:0px 0%; '><div style=\"text-align: center;\r\n \r\n    opacity: 1;\r\n    background-repeat: no-repeat;\r\n    background-size: cover;;\"  class=\"test-shine\">\r\n<a href=\"https:\/\/www.invensislearning.com\/observability-foundation-certification-course\/\" rel=\"bookmark\" title=\"Observability Foundation Training Course\" style=\"color:#fff\">\r\n<div class=\"td-module-meta-info SlideBox\" style=\"background:linear-gradient(0deg,#FAD384,#F39381 100%,rgba(0,0,0,0));text-align:center;padding:30px\">\r\n\r\n<div class=\"tdb-module-title-wrap\"><p class=\"entry-title td-module-title\"  style=\"    color: #fff;\r\n    font-size: 18px !important;\r\n    margin: 36px auto;\">\r\n\r\nObservability Foundation Training Course\r\n<\/p><\/div>\r\n<\/div>\r\n<\/a>\r\n<\/div><\/div>\n<div id='sample_slider_slide01' class='sa_hover_container' style='padding:0% 2%; margin:0px 0%; background-color:rgba(0, 0, 0, 0); '><div style=\"text-align: center;\r\n \r\n    opacity: 1;\r\n    background-repeat: no-repeat;\r\n    background-size: cover;;\" class=\"test-shine\">\r\n\r\n<a href=\"https:\/\/www.invensislearning.com\/devops-foundation-certification-training\/\" rel=\"bookmark\" title=\"DevOps Foundation Certification Training\" style=\"color:#fff\">\r\n\r\n<div class=\"td-module-meta-info SlideBox\" style=\"background:linear-gradient(0deg,#AAC4E6,#4C73BE 100%,rgba(0,0,0,0));text-align:center;padding:30px;margin-bottom:0\">\r\n\r\n<div class=\"tdb-module-title-wrap\"><p class=\"entry-title td-module-title\"  style=\"    color: #fff;\r\n    font-size: 18px !important;\r\n    margin: 36px auto;\">\r\n\r\n DevOps Foundation Certification Training\r\n<\/p><\/div>\r\n<\/div>\r\n<\/a>\r\n<\/div><\/div>\n<\/div>\n<\/div>\n<script type='text\/javascript'>\n\tjQuery(document).ready(function() {\n\t\tjQuery('#sample_slider').owlCarousel({\n\t\t\tresponsive:{\n\t\t\t\t0:{ items:1 },\n\t\t\t\t480:{ items:2 },\n\t\t\t\t768:{ items:2 },\n\t\t\t\t980:{ items:2 },\n\t\t\t\t1200:{ items:2 },\n\t\t\t\t1500:{ items:2 }\n\t\t\t},\n\t\t\tautoplay : true,\n\t\t\tautoplayTimeout : 4000,\n\t\t\tautoplayHoverPause : true,\n\t\t\tsmartSpeed : 300,\n\t\t\tfluidSpeed : 300,\n\t\t\tautoplaySpeed : 300,\n\t\t\tnavSpeed : 300,\n\t\t\tdotsSpeed : 300,\n\t\t\tloop : true,\n\t\t\tnav : true,\n\t\t\tnavText : ['Previous','Next'],\n\t\t\tdots : true,\n\t\t\tresponsiveRefreshRate : 200,\n\t\t\tslideBy : 1,\n\t\t\tmergeFit : true,\n\t\t\tautoHeight : false,\n\t\t\tmouseDrag : false,\n\t\t\ttouchDrag : true\n\t\t});\n\t\tjQuery('#sample_slider').css('visibility', 'visible');\n\t\tsa_resize_sample_slider();\n\t\twindow.addEventListener('resize', sa_resize_sample_slider);\n\t\tfunction sa_resize_sample_slider() {\n\t\t\tvar min_height = '50';\n\t\t\tvar win_width = jQuery(window).width();\n\t\t\tvar slider_width = jQuery('#sample_slider').width();\n\t\t\tif (win_width < 480) {\n\t\t\t\tvar slide_width = slider_width \/ 1;\n\t\t\t} else if (win_width < 768) {\n\t\t\t\tvar slide_width = slider_width \/ 2;\n\t\t\t} else if (win_width < 980) {\n\t\t\t\tvar slide_width = slider_width \/ 2;\n\t\t\t} else if (win_width < 1200) {\n\t\t\t\tvar slide_width = slider_width \/ 2;\n\t\t\t} else if (win_width < 1500) {\n\t\t\t\tvar slide_width = slider_width \/ 2;\n\t\t\t} else {\n\t\t\t\tvar slide_width = slider_width \/ 2;\n\t\t\t}\n\t\t\tslide_width = Math.round(slide_width);\n\t\t\tvar slide_height = '0';\n\t\t\tif (min_height == 'aspect43') {\n\t\t\t\tslide_height = (slide_width \/ 4) * 3;\t\t\t\tslide_height = Math.round(slide_height);\n\t\t\t} else if (min_height == 'aspect169') {\n\t\t\t\tslide_height = (slide_width \/ 16) * 9;\t\t\t\tslide_height = Math.round(slide_height);\n\t\t\t} else {\n\t\t\t\tslide_height = (slide_width \/ 100) * min_height;\t\t\t\tslide_height = Math.round(slide_height);\n\t\t\t}\n\t\t\tjQuery('#sample_slider .owl-item .sa_hover_container').css('min-height', slide_height+'px');\n\t\t}\n\t\tvar owl_goto = jQuery('#sample_slider');\n\t\tjQuery('.sample_slider_goto1').click(function(event){\n\t\t\towl_goto.trigger('to.owl.carousel', 0);\n\t\t});\n\t\tjQuery('.sample_slider_goto2').click(function(event){\n\t\t\towl_goto.trigger('to.owl.carousel', 1);\n\t\t});\n\t\tjQuery('.sample_slider_goto3').click(function(event){\n\t\t\towl_goto.trigger('to.owl.carousel', 2);\n\t\t});\n\t\tvar resize_9852 = jQuery('.owl-carousel');\n\t\tresize_9852.on('initialized.owl.carousel', function(e) {\n\t\t\tif (typeof(Event) === 'function') {\n\t\t\t\twindow.dispatchEvent(new Event('resize'));\n\t\t\t} else {\n\t\t\t\tvar evt = window.document.createEvent('UIEvents');\n\t\t\t\tevt.initUIEvent('resize', true, false, window, 0);\n\t\t\t\twindow.dispatchEvent(evt);\n\t\t\t}\n\t\t});\n\t});\n<\/script>\n<\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Continuous Integration and Continuous Deployment (CI\/CD) has become the cornerstone of modern software development, with 87% of high-performing DevOps teams deploying code multiple times per day, compared to once per month for low performers. AWS, commanding 32% of the global cloud infrastructure market, provides a comprehensive suite of native CI\/CD services that integrate seamlessly with [&hellip;]<\/p>\n","protected":false},"author":3,"featured_media":27050,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[3],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v16.7 (Yoast SEO v16.7) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>How to Build a CI\/CD Pipeline on AWS: A Detailed Guide<\/title>\n<meta name=\"description\" content=\"Learn how to build a CI\/CD pipeline on AWS using CodePipeline, CodeBuild, CodeDeploy, and CodeCommit with a step-by-step guide for automated releases.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.invensislearning.com\/blog\/how-to-build-ci-cd-pipeline-on-aws\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"How to Build a CI\/CD Pipeline on AWS: Complete Step-by-Step Guide\" \/>\n<meta property=\"og:description\" content=\"Learn how to build a CI\/CD pipeline on AWS using CodePipeline, CodeBuild, CodeDeploy, and CodeCommit with a step-by-step guide for automated releases.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.invensislearning.com\/blog\/how-to-build-ci-cd-pipeline-on-aws\/\" \/>\n<meta property=\"og:site_name\" content=\"Invensis Learning Blog\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/invensislearn\/\" \/>\n<meta property=\"article:published_time\" content=\"2026-01-13T12:35:10+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-03-03T06:51:25+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.invensislearning.com\/blog\/wp-content\/uploads\/2026\/01\/how-to-build-ci-cd-pipeline-on-aws-banner-image.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1500\" \/>\n\t<meta property=\"og:image:height\" content=\"1000\" \/>\n<meta name=\"twitter:card\" content=\"summary\" \/>\n<meta name=\"twitter:creator\" content=\"@InvensisElearn\" \/>\n<meta name=\"twitter:site\" content=\"@InvensisElearn\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Ethan Miller\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"24 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.invensislearning.com\/blog\/#organization\",\"name\":\"Invensis Learning\",\"url\":\"https:\/\/www.invensislearning.com\/blog\/\",\"sameAs\":[\"https:\/\/www.facebook.com\/invensislearn\/\",\"https:\/\/www.instagram.com\/invensis_learn\/\",\"https:\/\/www.linkedin.com\/company\/invensis-learning\/\",\"https:\/\/www.youtube.com\/channel\/UCq4xOlJ4xz6Fw7WcbFkrsUQ\",\"https:\/\/twitter.com\/InvensisElearn\"],\"logo\":{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/www.invensislearning.com\/blog\/#logo\",\"inLanguage\":\"en-US\",\"url\":\"https:\/\/www.invensislearning.com\/blog\/wp-content\/uploads\/2015\/06\/invensislogo-1.png\",\"contentUrl\":\"https:\/\/www.invensislearning.com\/blog\/wp-content\/uploads\/2015\/06\/invensislogo-1.png\",\"width\":181,\"height\":47,\"caption\":\"Invensis Learning\"},\"image\":{\"@id\":\"https:\/\/www.invensislearning.com\/blog\/#logo\"}},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.invensislearning.com\/blog\/#website\",\"url\":\"https:\/\/www.invensislearning.com\/blog\/\",\"name\":\"Invensis Learning Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/www.invensislearning.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.invensislearning.com\/blog\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/www.invensislearning.com\/blog\/how-to-build-ci-cd-pipeline-on-aws\/#primaryimage\",\"inLanguage\":\"en-US\",\"url\":\"https:\/\/www.invensislearning.com\/blog\/wp-content\/uploads\/2026\/01\/how-to-build-ci-cd-pipeline-on-aws-banner-image.jpg\",\"contentUrl\":\"https:\/\/www.invensislearning.com\/blog\/wp-content\/uploads\/2026\/01\/how-to-build-ci-cd-pipeline-on-aws-banner-image.jpg\",\"width\":1500,\"height\":1000,\"caption\":\"How to Build a CI\/CD Pipeline on AWS: Complete Step-by-Step Guide\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.invensislearning.com\/blog\/how-to-build-ci-cd-pipeline-on-aws\/#webpage\",\"url\":\"https:\/\/www.invensislearning.com\/blog\/how-to-build-ci-cd-pipeline-on-aws\/\",\"name\":\"How to Build a CI\/CD Pipeline on AWS: A Detailed Guide\",\"isPartOf\":{\"@id\":\"https:\/\/www.invensislearning.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.invensislearning.com\/blog\/how-to-build-ci-cd-pipeline-on-aws\/#primaryimage\"},\"datePublished\":\"2026-01-13T12:35:10+00:00\",\"dateModified\":\"2026-03-03T06:51:25+00:00\",\"description\":\"Learn how to build a CI\/CD pipeline on AWS using CodePipeline, CodeBuild, CodeDeploy, and CodeCommit with a step-by-step guide for automated releases.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.invensislearning.com\/blog\/how-to-build-ci-cd-pipeline-on-aws\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.invensislearning.com\/blog\/how-to-build-ci-cd-pipeline-on-aws\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.invensislearning.com\/blog\/how-to-build-ci-cd-pipeline-on-aws\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"How to Build a CI\/CD Pipeline on AWS: Complete Step-by-Step Guide\"}]},{\"@type\":\"Article\",\"@id\":\"https:\/\/www.invensislearning.com\/blog\/how-to-build-ci-cd-pipeline-on-aws\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.invensislearning.com\/blog\/how-to-build-ci-cd-pipeline-on-aws\/#webpage\"},\"author\":{\"@id\":\"https:\/\/www.invensislearning.com\/blog\/#\/schema\/person\/4c4c00b594b6452161a729498d551489\"},\"headline\":\"How to Build a CI\/CD Pipeline on AWS: Complete Step-by-Step Guide\",\"datePublished\":\"2026-01-13T12:35:10+00:00\",\"dateModified\":\"2026-03-03T06:51:25+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.invensislearning.com\/blog\/how-to-build-ci-cd-pipeline-on-aws\/#webpage\"},\"wordCount\":5573,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.invensislearning.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.invensislearning.com\/blog\/how-to-build-ci-cd-pipeline-on-aws\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.invensislearning.com\/blog\/wp-content\/uploads\/2026\/01\/how-to-build-ci-cd-pipeline-on-aws-banner-image.jpg\",\"articleSection\":[\"Trending Articles on DevOps\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.invensislearning.com\/blog\/how-to-build-ci-cd-pipeline-on-aws\/#respond\"]}]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.invensislearning.com\/blog\/#\/schema\/person\/4c4c00b594b6452161a729498d551489\",\"name\":\"Ethan Miller\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/www.invensislearning.com\/blog\/#personlogo\",\"inLanguage\":\"en-US\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/9360fb46958e5d91ec3e385e20116ef9?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/9360fb46958e5d91ec3e385e20116ef9?s=96&d=mm&r=g\",\"caption\":\"Ethan Miller\"},\"description\":\"Ethan Miller is a technology enthusiast with his major interest in DevOps adoption across industry sectors. He works as a DevOps Engineer and leads DevOps practices on Agile transformations. Ethan possesses 8+ years of experience in accelerating software delivery using innovative approaches and focuses on various aspects of the production phase to ensure timeliness and quality. He has varied experience in helping both private and public entities in the US and abroad to adopt DevOps and achieve efficient IT service delivery.\",\"url\":\"https:\/\/www.invensislearning.com\/blog\/author\/ethan\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"How to Build a CI\/CD Pipeline on AWS: A Detailed Guide","description":"Learn how to build a CI\/CD pipeline on AWS using CodePipeline, CodeBuild, CodeDeploy, and CodeCommit with a step-by-step guide for automated releases.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.invensislearning.com\/blog\/how-to-build-ci-cd-pipeline-on-aws\/","og_locale":"en_US","og_type":"article","og_title":"How to Build a CI\/CD Pipeline on AWS: Complete Step-by-Step Guide","og_description":"Learn how to build a CI\/CD pipeline on AWS using CodePipeline, CodeBuild, CodeDeploy, and CodeCommit with a step-by-step guide for automated releases.","og_url":"https:\/\/www.invensislearning.com\/blog\/how-to-build-ci-cd-pipeline-on-aws\/","og_site_name":"Invensis Learning Blog","article_publisher":"https:\/\/www.facebook.com\/invensislearn\/","article_published_time":"2026-01-13T12:35:10+00:00","article_modified_time":"2026-03-03T06:51:25+00:00","og_image":[{"width":1500,"height":1000,"url":"https:\/\/www.invensislearning.com\/blog\/wp-content\/uploads\/2026\/01\/how-to-build-ci-cd-pipeline-on-aws-banner-image.jpg","path":"\/home\/ubuntu\/dev\/blog\/invensislearning_blog\/wp-content\/uploads\/2026\/01\/how-to-build-ci-cd-pipeline-on-aws-banner-image.jpg","size":"full","id":27050,"alt":"How to Build a CI\/CD Pipeline on AWS: Complete Step-by-Step Guide","pixels":1500000,"type":"image\/jpeg"}],"twitter_card":"summary","twitter_creator":"@InvensisElearn","twitter_site":"@InvensisElearn","twitter_misc":{"Written by":"Ethan Miller","Est. reading time":"24 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Organization","@id":"https:\/\/www.invensislearning.com\/blog\/#organization","name":"Invensis Learning","url":"https:\/\/www.invensislearning.com\/blog\/","sameAs":["https:\/\/www.facebook.com\/invensislearn\/","https:\/\/www.instagram.com\/invensis_learn\/","https:\/\/www.linkedin.com\/company\/invensis-learning\/","https:\/\/www.youtube.com\/channel\/UCq4xOlJ4xz6Fw7WcbFkrsUQ","https:\/\/twitter.com\/InvensisElearn"],"logo":{"@type":"ImageObject","@id":"https:\/\/www.invensislearning.com\/blog\/#logo","inLanguage":"en-US","url":"https:\/\/www.invensislearning.com\/blog\/wp-content\/uploads\/2015\/06\/invensislogo-1.png","contentUrl":"https:\/\/www.invensislearning.com\/blog\/wp-content\/uploads\/2015\/06\/invensislogo-1.png","width":181,"height":47,"caption":"Invensis Learning"},"image":{"@id":"https:\/\/www.invensislearning.com\/blog\/#logo"}},{"@type":"WebSite","@id":"https:\/\/www.invensislearning.com\/blog\/#website","url":"https:\/\/www.invensislearning.com\/blog\/","name":"Invensis Learning Blog","description":"","publisher":{"@id":"https:\/\/www.invensislearning.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.invensislearning.com\/blog\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"ImageObject","@id":"https:\/\/www.invensislearning.com\/blog\/how-to-build-ci-cd-pipeline-on-aws\/#primaryimage","inLanguage":"en-US","url":"https:\/\/www.invensislearning.com\/blog\/wp-content\/uploads\/2026\/01\/how-to-build-ci-cd-pipeline-on-aws-banner-image.jpg","contentUrl":"https:\/\/www.invensislearning.com\/blog\/wp-content\/uploads\/2026\/01\/how-to-build-ci-cd-pipeline-on-aws-banner-image.jpg","width":1500,"height":1000,"caption":"How to Build a CI\/CD Pipeline on AWS: Complete Step-by-Step Guide"},{"@type":"WebPage","@id":"https:\/\/www.invensislearning.com\/blog\/how-to-build-ci-cd-pipeline-on-aws\/#webpage","url":"https:\/\/www.invensislearning.com\/blog\/how-to-build-ci-cd-pipeline-on-aws\/","name":"How to Build a CI\/CD Pipeline on AWS: A Detailed Guide","isPartOf":{"@id":"https:\/\/www.invensislearning.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.invensislearning.com\/blog\/how-to-build-ci-cd-pipeline-on-aws\/#primaryimage"},"datePublished":"2026-01-13T12:35:10+00:00","dateModified":"2026-03-03T06:51:25+00:00","description":"Learn how to build a CI\/CD pipeline on AWS using CodePipeline, CodeBuild, CodeDeploy, and CodeCommit with a step-by-step guide for automated releases.","breadcrumb":{"@id":"https:\/\/www.invensislearning.com\/blog\/how-to-build-ci-cd-pipeline-on-aws\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.invensislearning.com\/blog\/how-to-build-ci-cd-pipeline-on-aws\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.invensislearning.com\/blog\/how-to-build-ci-cd-pipeline-on-aws\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"How to Build a CI\/CD Pipeline on AWS: Complete Step-by-Step Guide"}]},{"@type":"Article","@id":"https:\/\/www.invensislearning.com\/blog\/how-to-build-ci-cd-pipeline-on-aws\/#article","isPartOf":{"@id":"https:\/\/www.invensislearning.com\/blog\/how-to-build-ci-cd-pipeline-on-aws\/#webpage"},"author":{"@id":"https:\/\/www.invensislearning.com\/blog\/#\/schema\/person\/4c4c00b594b6452161a729498d551489"},"headline":"How to Build a CI\/CD Pipeline on AWS: Complete Step-by-Step Guide","datePublished":"2026-01-13T12:35:10+00:00","dateModified":"2026-03-03T06:51:25+00:00","mainEntityOfPage":{"@id":"https:\/\/www.invensislearning.com\/blog\/how-to-build-ci-cd-pipeline-on-aws\/#webpage"},"wordCount":5573,"commentCount":0,"publisher":{"@id":"https:\/\/www.invensislearning.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.invensislearning.com\/blog\/how-to-build-ci-cd-pipeline-on-aws\/#primaryimage"},"thumbnailUrl":"https:\/\/www.invensislearning.com\/blog\/wp-content\/uploads\/2026\/01\/how-to-build-ci-cd-pipeline-on-aws-banner-image.jpg","articleSection":["Trending Articles on DevOps"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.invensislearning.com\/blog\/how-to-build-ci-cd-pipeline-on-aws\/#respond"]}]},{"@type":"Person","@id":"https:\/\/www.invensislearning.com\/blog\/#\/schema\/person\/4c4c00b594b6452161a729498d551489","name":"Ethan Miller","image":{"@type":"ImageObject","@id":"https:\/\/www.invensislearning.com\/blog\/#personlogo","inLanguage":"en-US","url":"https:\/\/secure.gravatar.com\/avatar\/9360fb46958e5d91ec3e385e20116ef9?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/9360fb46958e5d91ec3e385e20116ef9?s=96&d=mm&r=g","caption":"Ethan Miller"},"description":"Ethan Miller is a technology enthusiast with his major interest in DevOps adoption across industry sectors. He works as a DevOps Engineer and leads DevOps practices on Agile transformations. Ethan possesses 8+ years of experience in accelerating software delivery using innovative approaches and focuses on various aspects of the production phase to ensure timeliness and quality. He has varied experience in helping both private and public entities in the US and abroad to adopt DevOps and achieve efficient IT service delivery.","url":"https:\/\/www.invensislearning.com\/blog\/author\/ethan\/"}]}},"_links":{"self":[{"href":"https:\/\/www.invensislearning.com\/blog\/wp-json\/wp\/v2\/posts\/27049"}],"collection":[{"href":"https:\/\/www.invensislearning.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.invensislearning.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.invensislearning.com\/blog\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/www.invensislearning.com\/blog\/wp-json\/wp\/v2\/comments?post=27049"}],"version-history":[{"count":1,"href":"https:\/\/www.invensislearning.com\/blog\/wp-json\/wp\/v2\/posts\/27049\/revisions"}],"predecessor-version":[{"id":27053,"href":"https:\/\/www.invensislearning.com\/blog\/wp-json\/wp\/v2\/posts\/27049\/revisions\/27053"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.invensislearning.com\/blog\/wp-json\/wp\/v2\/media\/27050"}],"wp:attachment":[{"href":"https:\/\/www.invensislearning.com\/blog\/wp-json\/wp\/v2\/media?parent=27049"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.invensislearning.com\/blog\/wp-json\/wp\/v2\/categories?post=27049"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}