Skip to content

CI/CD


Once we've provisioned everything, we'll need to automate it. This is the final stage of this book.

The whole automation process, at a high level, looks like this:

graph LR
    A[Code Change] --> B[git commit]
    B --> C[git push]
    C --> D[GitLab]
    D --> E[CI]
    E --> F[CD]
    F --> G[AWS]

Continuous Integration (CI)

When we have an application that we want to test and build automatically after a change is made, we use Continuous Integration (CI). Testing involves running unit and modules tests, or more, and building involves producing a compiled version of our application that can be executed on hosts. This is called an artefact or a package.

Our application CI process is simple:

graph LR
    A[Change] --> S1[Linting]

    subgraph CI
    S1 --> S2[Testing]
    S2 --> S3[Compiling]
    S3 --> S4[artefact]
    end

CI is also used to run tests against our Terraform and Ansible code bases, although we don't currently have any such tests yet. What we can do for the time being is simply use terraform fmt -check to perform a linting check on our code. We can do the same for our Ansible code, too.

So our Terraform and Ansible CI processes are simple too:

graph LR
    A[Change] --> S1[Linting]

    subgraph CI
    S1
    end

Technically Terraform produces a plan that we use to decide if we want to make the changes or not, but it's not really an artefact in the tradition sense.

Neither Terraform nor Ansible require compiling at all.

Continuous Delivery (CD)

After we've built an artefact for our application, or we've finished validating the changes made via Terraform or Ansible, it's time to deploy what we've done. This is called Continuous Delivery (CD) or Continuous Deployment.

At the infrastructure level changes to the Terraform code need to produce a plan, which needs to be approved, which then results in changes going live.

This looks a bit like this:

graph LR
    a[Change] --> b[terraform plan]
    b -- Approved --> c[terraform apply]
    b -- Rejected --> d[stop pipeline]

With changes to our application packaged and ready to go, we automate Ansible into a CD pipeline. Ansible doesn't technically have a planning stage, but we can run a "dry run", which is what we'll do. If we're happy with the results of the dry run then we can have the changes go ahead. If not, then we stop the pipeline.

graph LR
    a[Change] --> b[ansible-playbook --dry-run]
    b -- Approved --> c[ansible-playbook]
    b -- Rejected --> d[stop pipeline]

End-to-End (EtE)

Combined, we can develop completely end-to-end (EtE) automated pipelines for various changes.

Here's what a change to the application would look like, EtE:

graph LR
    a[Application Change] --> a1

    subgraph App CI
    a1[Testing] --> a2[Linting]
    a2 --> a3[Compiling]
    a3 --> a4[Packaging]
    end

    a4 --> b1

    subgraph Ansible CI
    b1[Dry Run] --> b2[Approved]
    b1 --> b3[Rejected]
    b2 --> b4[ansible-playbook]
    b3 --> b5[stop]
    end

It can get pretty complex, pretty quickly, and it will as we progress and advance the solution in this book over time.