Automating CloudFormation Deployments: The DevOps Way with AWS Git sync & GitHub Actions
Tags: cloudformation, gitsync, aws, github
Published: 2024-01-27 17:12:36

##Hey Devs, Let's Git This Party Started!

CloudFormation Git sync provides remote management of stacks, enabling customers to synchronize their stacks from a CloudFormation template stored in a remote Git repository. You can enable CloudFormation Git sync through the AWS Console, CLI, and SDKs. With Git sync, you can manage your CloudFormation stacks using source control it works with GitHub, GitHub enterprise, GitLab, and BitBucket.

[Step-by-Step Walk-Through Video](https://youtu.be/U7bYRBXK5JE)

**Kickoff: Setting Up Your GitHub Repo**

1.  **Hop into GitHub**: Just slide into your GitHub account. No account yet? No sweat, signing up is a breeze.
2.  **Dashboard Time**: Once you're in, you're gonna land on your dashboard. It's your command center.
3.  **Repo Magic**:

-   Hit the '+' sign up top. Feels like unlocking a treasure, right?
-   Choose 'New Repository' from the dropdown.

5.  **Repo Details**:

-   Name your brainchild.
-   Public or Private? Your call.
-   Add a catchy description.
-   Init with a README? Always a smart move.
-   Pick a license if you're feeling it.

7.  **Create It**: Smash that 'Create repository' button.
8.  **Bam! Repository Ready**: Your new digital playground is set on GitHub.

**Securing the Fort with a Token**

1.  **Settings, Please**: Click your profile pic and hit 'Settings'.
2.  **Developer Mode On**: Find 'Developer settings' on the left.
3.  **Token Time**: Under 'Access Tokens', select 'Personal access tokens'.
4.  **Token Generation**:

-   Click 'Generate token'. Feels like launching a rocket, huh?
-   Name it something cool.
-   Pick the powers (permissions) wisely.
-   Expiry date? Your choice.

6.  **Copy That Token**: Guard it like a secret treasure.

**Local Repo Clone: Bringing it Home**

1.  **Git Ready**: No Git? Download it from the Git website.
2.  **Terminal or Command Prompt**: Open it. It's like opening the door to Narnia.
3.  **Directory Navigation**:

-   Use 'cd' to move to your desired folder. Desktop? **cd ~/Desktop**.

5.  **Clone Command**:

-   **git clone <repository-url>**
-   Replace **<repository-url>** with yours.

7.  **Token Authentication**: Private repo? Use your token as the password.
8.  **Cloned and Ready**: Your repo's now on your local machine. Time to make magic!

**Crafting Your CloudFormation Template.yaml**

1.  **New File in IDE**: Click 'File' > 'New File'.
2.  **Save with .yaml Extension**: Name it like 'cfn-template.yaml'.
3.  **Template Time**: Paste your CloudFormation template here.

```
AWSTemplateFormatVersion: 2010-09-09

Description: This is my gitsync demo template

Resources:

  GitsyncVpc:

    Type: AWS::EC2::VPC

    Properties:

      CidrBlock: 10.0.0.1/16

      EnableDnsSupport: true

      Tags:

        - Key: Name

          Value: gitsyncvpc

  GitsyncSubnet:

    Type: AWS::EC2::Subnet

    Properties:

      VpcId: !Ref GitsyncVpc

      CidrBlock: 10.0.0.1/24

      Tags:

        - Key: keyname

          Value: value
```

**Template Validation: No Errors Allowed**

1.  **Save and Validate**: Run **cfn-lint -t <yourfile>.yaml** in your terminal. To check your template for any syntax errors and provide feedback in the Output pane - keep it error-free.

If you don't have cfn-lint installed, you can install it with the following command:
```
pip3 install cfn-lint
```

**Deployment File: Setting Up for Success**

1.  **New File Again**: In your IDE, 'File' > 'New File'.
2.  **Save as 'deployment-file.yaml'**.
3.  **Path and Tags**: Include the file path of your CloudFormation template and any tags.

```
template-file-path: ./cfn-temp.yaml

tags:

    Name: 'gitsync'

    Project: 'Demo'
```

**GitHub Actions: Keeping Your Code in Check**

-   Setup and establish the following folder structure:  **.github/workflows/pull-request.yaml**.
-   Define workflow to lint your pull requests.

```
name: Pull Request workflow

on:

  - pull_request

jobs:

  cloudformation-linter:

    runs-on: ubuntu-latest

    steps:

      - name: Checkout

        uses: actions/checkout@v3

      - name: Linter install

        uses: scottbrenner/cfn-lint-action@v2

        with:

          command: cfn-lint -t ./cfn-temp.yaml
```

**Branching and Committing: Own Your Updates**

- Create a new branch

- Add and commit your configs.

```
git switch -c gitSync-updateBranch

git add -A

git commit -m "add gitsync configs"

git push origin gitSync-updateBranch
```

**Git Sync Prereqs: Keep Your Stack in Sync**

1.  **AWS Console Login**: Head over to the AWS Management Console.
2.  **Developer Tools Connection**:

-   Search ' Code Pipeline ' in AWS services.
-   Navigate to Connections
-   Create a new connection to GitHub.

![serch codepipeline](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kok6zo7ulfkrk5n9wmni.png)
![choose connections](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/abl2qya6yxdt0b63oz49.png)
![create connection](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fzlb4ljl51ebde4uujds.png)


1.  **IAM Role Creation**: Create the role that will deploy our CloudFormation template. Be sure to note the name you select for this as you'll be using it to manage your stack later. This example uses gitsync-cloudformation-deployment-role.

-   Navigate ' IAM ' in AWS services.
-   Navigate to Connections
-   Create a new role for Cloudformaton. (gitsync-demo-role)
-   Create an inline policy for the role. (gitsync-demorole-policy)
```
JSON:

{

    "Version": "2012-10-17",

    "Statement": [

        {

            "Effect": "Allow",

            "Action": [

                "ec2:CreateVpc",

                "ec2:CreateSubnet",

                "ec2:DescribeVpcs",

                "ec2:DescribeSubnets",

                "ec2:DeleteVpc",

                "ec2:DeleteSubnet",

                "ec2:ModifySubnetAttribute",

                "ec2:CreateTags",

                "ec2:ModifyVpcAttribute"

            ],

            "Resource": "*",

            "Condition": {

                "ForAnyValue:StringEquals": {

                    "aws:CalledVia": [

                        "cloudformation.amazonaws.com"

                    ]

                }

            }

        }

    ]

}
```
**Link up with CloudFormation!**

Once the role has been created, you'll create a new Stack:

Here, you can see the new option to select Sync from Git template source, which you can configure on the next screen. Since you already created your stack deployment file, you can select I am providing my own file in my repository.
![create stack](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iind1fing6ikwu9uaaw6.png)
![stack file](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0jsgzrliwi93bbneza0l.png)
Next, you can configure your Git integration to choose your repository. You'll need to use the Connection you created beforehand and select your repository. Select GitHub, your connection, the repository, and branch, the deployment file location.
![stack config](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9ien6cku4kk9slja7sy0.png)
Now, you will select New IAM Role to create a service managed role. This role will enable Git sync to connect to your repository. The role will be re-usable.
![stack role](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lajgpwjqz758pgd4d0t0.png)
On the next page, you'll select the IAM Role you created earlier to manage this stack. This role controls the resources that CloudFormation will deploy..
![stack perm role](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h0labcrv35y9vt9h8ymk.png)
Finally, you can see the status of your sync in the new "Git sync" tab, including the configuration you provided earlier as well as the status of your sync, your previous deployments, and the option to retry or disconnect the sync if needed.
![git sync](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gmyjmh423p95es650zis.png)

**Give It a Whirl**

1.  **Get over to GitHub**: log into your Github account.
2.  **Create a Pull Request**: Create a new pull request and wait for lint checks to pass.
3.  **Merge Pull Request**: Include the file path of your CloudFormation template and any tags.
![pull request](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pno4ogqy7wzj97acfuai.png)
![checks](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/froehyrgdmfldn9cwrqd.png)
![checks pass](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1kb2305r3zuiiecfklyq.png)
Return to the CloudFormation Console and see that the stack is being provisioned. You can also look at the stack details to see the events, outputs, etc.
![in progress](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rim7pctr3wwzr7gxc3d4.png)
When the sync is complete Git sync will show the provisioning status as succeeded and the stack with all its resources will be deployed.
![git sync status](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/efexjaelpruenunsdxwn.png)
![sync success](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hrgerysg0hu0u8y3x399.png)

**Conclusion: Wrapping Up Like a Pro**

You've just set up a slick, automated environment for CloudFormation templates. Validation on pull requests and auto-deployment to your stack? Now when your repo/template is updated and merged gitsync will automatically make the changes to your cloudformation stack and resources. We got this! This is that next-level CI/CD for your infrastructure code, a brand new workflow for me, and as always Builder Fun!