Architecting CI/CD Pipelines: AWS CodePipeline and GitHub Actions for Static Deployments

The convergence of Infrastructure as Code (IaC), automated testing, and cloud-native deployment tools has fundamentally reshaped how development teams deliver software. Continuous Integration (CI) and Continuous Delivery (CD) are no longer just technical processes; they represent a cultural shift toward rapid, reliable, and secure software release cycles. This article explores two distinct yet complementary approaches to achieving this goal: using AWS CDK to construct an AWS CodePipeline for enterprise-grade automation, and leveraging GitHub Actions to deploy static sites directly to AWS EC2 instances. Both methods emphasize repeatability, security validation, and the elimination of manual intervention in the deployment lifecycle.

AWS CDK and CodePipeline Architecture

Implementing a robust CI/CD pipeline requires a framework that ensures every code change undergoes rigorous validation before reaching production. AWS Cloud Development Kit (CDK) provides a powerful mechanism to define these pipelines as code, allowing developers to model complex release processes using familiar programming languages. The primary intent of this architectural pattern is to accelerate deployment while strictly adhering to DevOps best practices, including automated security checks and linting.

AWS CodePipeline serves as the central orchestration service. It models the software release process through distinct stages, often integrating with AWS CodeBuild for compilation and packaging, and AWS CodeDeploy for artifact distribution across fleets of EC2 instances. By defining the pipeline in CDK v2, teams can synthesize CloudFormation templates that deploy the entire CI/CD infrastructure automatically, ensuring that the resources themselves are built consistently and securely.

Initializing the CDK Project

To begin constructing the pipeline, the developer must first acquire the reference implementation and prepare the local environment. The process starts by cloning the repository and removing the existing Git history, as the pipeline will manage the source code through AWS CodeCommit rather than the original Git history.

bash git clone --depth 1 https://github.com/aws-samples/aws-codepipeline-cicd.git cd ./aws-codepipeline-cicd rm -rf ./.git

With the local repository cleaned, the next step involves installing dependencies and bootstrapping the AWS environment. This ensures that the CDK toolkit can deploy the infrastructure to the correct account and region.

bash AWS_REGION="eu-west-1" ACCOUNT_NUMBER=$(aws sts get-caller-identity --query Account --output text) echo "${ACCOUNT_NUMBER}" npm install npm run build npm run cdk bootstrap "aws://${ACCOUNT_NUMBER}/${AWS_REGION}"

Upon successful bootstrapping, the CDK toolkit converts the application code into CloudFormation templates and deploys them. The synthesis step validates the infrastructure definition.

bash npm run cdk synth

After synthesis, the developer can deploy the CodePipeline stack. This action creates the actual pipeline resources in AWS, including the CodeCommit repository that will serve as the source control system for the pipeline.

Connecting to AWS CodeCommit

A critical phase in this architecture is linking the local development environment to the newly created AWS CodeCommit repository. This ensures that commits made locally are pushed to the AWS-side repository, which triggers the pipeline. The repository name is retrieved from the CloudFormation stack outputs, ensuring the correct remote origin is established.

bash RepoName=$(aws cloudformation describe-stacks --stack-name CodePipeline --query "Stacks[0].Outputs[?OutputKey=='RepositoryName'].OutputValue" --output text) echo "${RepoName}" git init git branch -m master main git remote add origin codecommit://${RepoName} git add . git commit -m "Initial commit" git push -u origin main

Once the initial commit is pushed, the AWS CodePipeline activates. The pipeline executes a defined sequence of actions: it retrieves code from CodeCommit, builds the application, updates the pipeline configuration (SelfMutate), and runs three parallel jobs for linting, security analysis, and unit tests. If these checks pass, the pipeline deploys the main infrastructure stack and performs post-deployment validation. This sequence ensures that only validated, secure code reaches the production environment.

GitHub Actions for EC2 Deployment

While AWS CodePipeline offers a comprehensive, managed CI/CD solution, developers often seek lighter-weight alternatives for simpler use cases, such as deploying static HTML sites. GitHub Actions provides an efficient mechanism to automate deployments directly to AWS EC2 instances without the overhead of a full CodePipeline setup. This approach is particularly effective for small teams or projects that require rapid iteration on static content.

Configuring the EC2 Instance

To support this deployment model, the target EC2 instance must be properly configured with a web server. The process begins with launching an instance in the AWS Console, selecting Amazon Linux 2 or Ubuntu, and ensuring appropriate security group rules are in place to allow SSH (port 22) and HTTP (port 80) traffic.

```bash

Move the PEM key to a secure location and set permissions

mv ~/Downloads/your-key.pem ~/.ssh/
chmod 400 ~/.ssh/your-key.pem

SSH into the instance

ssh -i ~/.ssh/your-key.pem ec2-user@your-ec2-public-ip
```

Once connected, the developer installs and configures the Apache web server. The specific commands depend on the operating system chosen during instance launch.

```bash

For Amazon Linux 2

sudo yum update -y
sudo yum install -y httpd
sudo systemctl start httpd
sudo systemctl enable httpd
sudo chown ec2-user /var/www/html

For Ubuntu

sudo apt update
sudo apt install -y apache2
sudo systemctl start apache2
sudo systemctl enable apache2
sudo chown ubuntu /var/www/html
```

After installation, verifying that the Apache test page loads at the instance's public IP confirms the server is operational and ready to receive deployed content.

Automating with GitHub Actions

The core of this automated workflow is a GitHub Actions configuration file, typically named deploy.yml, located in the .github/workflows directory. This file defines a job that triggers on every push to the main branch. The job uses the scp-action to securely copy the index.html file to the EC2 instance's web root directory.

```yaml
name: Deploy to EC2
on:
push:
branches:
- main

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v3

  - name: Copy files via SCP
    uses: appleboy/[email protected]
    with:
      host: ${{ secrets.EC2_HOST }}
      username: ${{ secrets.EC2_USER }}
      key: ${{ secrets.EC2_KEY }}
      source: "index.html"
      target: "/var/www/html"

```

For this workflow to function securely, sensitive connection details must be stored as GitHub Secrets. These include the EC2 host IP, the username (either ec2-user or ubuntu), and the private key content. GitHub Secrets are encrypted, providing a secure method for credential management, though for production-grade setups, using IAM roles or session-based credentials is recommended to further minimize exposure.

```bash

Commit and push the workflow configuration

git add .
git commit -m "Initial CI/CD setup"
git push origin main
```

Once pushed, navigating to the Actions tab in the GitHub repository reveals the running deploy job. Upon successful completion, the website updates automatically, demonstrating the efficacy of automated delivery.

Conclusion

The transition to automated CI/CD pipelines represents a critical evolution in software engineering, shifting the focus from manual deployment to reliable, repeatable processes. Whether utilizing the robust, enterprise-scale AWS CodePipeline driven by CDK, or the agile, developer-friendly GitHub Actions workflow, the underlying objective remains consistent: to accelerate delivery while enforcing security and quality checks. By embedding linting, security scanning, and unit testing into the pipeline, development teams can ensure that every code change is validated before it reaches the user. These tools not only reduce the risk of human error but also foster a culture of continuous improvement, where infrastructure and application code are treated with equal rigor.

Sources

  1. AWS CodePipeline CI/CD Sample

  2. CI/CD for Beginners: Deploy a Static HTML Site to AWS EC2 with GitHub Actions

Related Posts