Skip to main content

Module: cicd

Terraform module to create AWS CodePipeline with CodeBuild for CI/CD

This module supports three use-cases:

  1. GitHub -> S3 (build artifact) -> Elastic Beanstalk (running application stack). The module gets the code from a GitHub repository (public or private), builds it by executing the buildspec.yml file from the repository, pushes the built artifact to an S3 bucket, and deploys the artifact to Elastic Beanstalk running one of the supported stacks (e.g. Java, Go, Node, IIS, Python, Ruby, etc.).

  2. GitHub -> ECR (Docker image) -> Elastic Beanstalk (running Docker stack). The module gets the code from a GitHub repository, builds a Docker image from it by executing the buildspec.yml and Dockerfile files from the repository, pushes the Docker image to an ECR repository, and deploys the Docker image to Elastic Beanstalk running Docker stack.

  3. GitHub -> ECR (Docker image). The module gets the code from a GitHub repository, builds a Docker image from it by executing the buildspec.yml and Dockerfile files from the repository, and pushes the Docker image to an ECR repository. This is used when we want to build a Docker image from the code and push it to ECR without deploying to Elastic Beanstalk. To activate this mode, don't specify the app and env attributes for the module.

Usage

Include this repository as a module in your existing terraform code:

module "build" {
source = "cloudposse/cicd/aws"
# Cloud Posse recommends pinning every module to a specific version
# version = "x.x.x"
namespace = "eg"
stage = "staging"
name = "app"

# Enable the pipeline creation
enabled = true

# Elastic Beanstalk
elastic_beanstalk_application_name = "<(Optional) Elastic Beanstalk application name>"
elastic_beanstalk_environment_name = "<(Optional) Elastic Beanstalk environment name>"

# Application repository on GitHub
github_oauth_token = "(Required) <GitHub Oauth Token with permissions to access private repositories>"
repo_owner = "<GitHub Organization or Person name>"
repo_name = "<GitHub repository name of the application to be built and deployed to Elastic Beanstalk>"
branch = "<Branch of the GitHub repository>"

# http://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref.html
# http://docs.aws.amazon.com/codebuild/latest/userguide/build-spec-ref.html
build_image = "aws/codebuild/standard:2.0"
build_compute_type = "BUILD_GENERAL1_SMALL"

# These attributes are optional, used as ENV variables when building Docker images and pushing them to ECR
# For more info:
# http://docs.aws.amazon.com/codebuild/latest/userguide/sample-docker.html
# https://www.terraform.io/docs/providers/aws/r/codebuild_project.html
privileged_mode = true
region = "us-east-1"
aws_account_id = "xxxxxxxxxx"
image_repo_name = "ecr-repo-name"
image_tag = "latest"

# Optional extra environment variables
environment_variables = [{
name = "JENKINS_URL"
value = "https://jenkins.example.com"
},
{
name = "COMPANY_NAME"
value = "Amazon"
},
{
name = "TIME_ZONE"
value = "Pacific/Auckland"
}]
}

Examples

Example: GitHub, NodeJS, S3 and EB

This is an example to build a Node app, store the build artifact to an S3 bucket, and then deploy it to Elastic Beanstalk running Node stack

buildspec.yml file

version: 0.2

phases:
install:
commands:
- echo Starting installation ...
pre_build:
commands:
- echo Installing NPM dependencies...
- npm install
build:
commands:
- echo Build started on `date`
post_build:
commands:
- echo Build completed on `date`
artifacts:
files:
- node_modules/**/*
- public/**/*
- routes/**/*
- views/**/*
- app.js

Example: GitHub, NodeJS, Docker, ECR and EB

This is an example to build a Docker image for a Node app, push the Docker image to an ECR repository, and then deploy it to Elastic Beanstalk running Docker stack

buildspec.yml file

version: 0.2

phases:
pre_build:
commands:
- echo Logging in to Amazon ECR...
- $(aws ecr get-login --region $AWS_REGION)
build:
commands:
- echo Build started on `date`
- echo Building the Docker image...
- docker build -t $IMAGE_REPO_NAME .
- docker tag $IMAGE_REPO_NAME:$IMAGE_TAG $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG
post_build:
commands:
- echo Build completed on `date`
- echo Pushing the Docker image to ECR...
- docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG
artifacts:
files:
- '**/*'

Dockerfile

FROM node:latest

WORKDIR /usr/src/app

COPY package.json package-lock.json ./
RUN npm install
COPY . .

EXPOSE 8081
CMD [ "npm", "start" ]

Variables

Required Variables

branch (string) required

Branch of the GitHub repository, e.g. master

github_oauth_token (string) required

GitHub Oauth Token

repo_name (string) required

GitHub repository name of the application to be built (and deployed to Elastic Beanstalk if configured)

repo_owner (string) required

GitHub Organization or Person name

Optional Variables

access_log_bucket_name (string) optional

Name of the S3 bucket where s3 access log will be sent to


Default value: ""

aws_account_id (string) optional

AWS Account ID. Used as CodeBuild ENV variable when building Docker images. For more info


Default value: ""

build_compute_type (string) optional

CodeBuild instance size. Possible values are: BUILD_GENERAL1_SMALL BUILD_GENERAL1_MEDIUM BUILD_GENERAL1_LARGE


Default value: "BUILD_GENERAL1_SMALL"

build_image (string) optional

Docker image for build environment, e.g. aws/codebuild/standard:2.0 or aws/codebuild/eb-nodejs-6.10.0-amazonlinux-64:4.0.0


Default value: "aws/codebuild/standard:2.0"

buildspec (string) optional

Declaration to use for building the project. For more info


Default value: ""

cache_type (string) optional

The type of storage that will be used for the AWS CodeBuild project cache. Valid values: NO_CACHE, LOCAL, and S3. Defaults to S3 to keep same behavior as before upgrading codebuild module to 0.18+ version. If cache_type is S3, it will create an S3 bucket for storing codebuild cache inside


Default value: "S3"

codebuild_cache_bucket_suffix_enabled (bool) optional

The cache bucket generates a random 13 character string to generate a unique bucket name. If set to false it uses terraform-null-label's id value


Default value: true

elastic_beanstalk_application_name (string) optional

Elastic Beanstalk application name. If not provided or set to empty string, the Deploy stage of the pipeline will not be created


Default value: ""

elastic_beanstalk_environment_name (string) optional

Elastic Beanstalk environment name. If not provided or set to empty string, the Deploy stage of the pipeline will not be created


Default value: ""

environment_variables optional

A list of maps, that contain the keys 'name', 'value', and 'type' to be used as additional environment variables for the build. Valid types are 'PLAINTEXT', 'PARAMETER_STORE', or 'SECRETS_MANAGER'


Type:

list(object(
{
name = string
value = string
type = string
}))

Default value:

[
{
"name": "NO_ADDITIONAL_BUILD_VARS",
"type": "PLAINTEXT",
"value": "TRUE"
}
]
force_destroy (bool) optional

Force destroy the CI/CD S3 bucket even if it's not empty


Default value: false

github_webhook_events (list(string)) optional

A list of events which should trigger the webhook. See a list of available events


Default value:

[
"push"
]
github_webhooks_token (string) optional

GitHub OAuth Token with permissions to create webhooks. If not provided, can be sourced from the GITHUB_TOKEN environment variable


Default value: ""

image_repo_name (string) optional

ECR repository name to store the Docker image built by this module. Used as CodeBuild ENV variable when building Docker images. For more info


Default value: "UNSET"

image_tag (string) optional

Docker image tag in the ECR repository, e.g. 'latest'. Used as CodeBuild ENV variable when building Docker images. For more info


Default value: "latest"

poll_source_changes (bool) optional

Periodically check the location of your source content and run the pipeline if changes are detected


Default value: true

privileged_mode (bool) optional

If set to true, enables running the Docker daemon inside a Docker container on the CodeBuild instance. Used when building Docker images


Default value: false

region (string) optional

AWS Region, e.g. us-east-1. Used as CodeBuild ENV variable when building Docker images. For more info


Default value: ""

s3_bucket_encryption_enabled (bool) optional

When set to 'true' the 'aws_s3_bucket' resource will have AES256 encryption enabled by default


Default value: true

versioning_enabled (bool) optional

A state of versioning. Versioning is a means of keeping multiple variants of an object in the same bucket


Default value: true

webhook_authentication (string) optional

The type of authentication to use. One of IP, GITHUB_HMAC, or UNAUTHENTICATED


Default value: "GITHUB_HMAC"

webhook_enabled (bool) optional

Set to false to prevent the module from creating any webhook resources


Default value: false

webhook_filter_json_path (string) optional

The JSON path to filter on


Default value: "$.ref"

webhook_filter_match_equals (string) optional

The value to match on (e.g. refs/heads/{Branch})


Default value: "refs/heads/{Branch}"

webhook_target_action (string) optional

The name of the action in a pipeline you want to connect to the webhook. The action must be from the source (first) stage of the pipeline


Default value: "Source"

website_bucket_acl (string) optional

Canned ACL of the S3 bucket objects that get served as a website, can be private if using CloudFront with OAI


Default value: "public-read"

website_bucket_name (string) optional

Name of the S3 bucket where the website will be deployed


Default value: ""

Context Variables

The following variables are defined in the context.tf file of this module and part of the terraform-null-label pattern.

additional_tag_map (map(string)) optional

Additional key-value pairs to add to each map in tags_as_list_of_maps. Not added to tags or id.
This is for some rare cases where resources want additional configuration of tags
and therefore take a list of maps with tag key, value, and additional configuration.


Required: No

Default value: { }

attributes (list(string)) optional

ID element. Additional attributes (e.g. workers or cluster) to add to id,
in the order they appear in the list. New attributes are appended to the
end of the list. The elements of the list are joined by the delimiter
and treated as a single ID element.


Required: No

Default value: [ ]

context (any) optional

Single object for setting entire context at once.
See description of individual variables for details.
Leave string and numeric variables as null to use default value.
Individual variable settings (non-null) override settings in context object,
except for attributes, tags, and additional_tag_map, which are merged.


Required: No

Default value:

{
"additional_tag_map": {},
"attributes": [],
"delimiter": null,
"descriptor_formats": {},
"enabled": true,
"environment": null,
"id_length_limit": null,
"label_key_case": null,
"label_order": [],
"label_value_case": null,
"labels_as_tags": [
"unset"
],
"name": null,
"namespace": null,
"regex_replace_chars": null,
"stage": null,
"tags": {},
"tenant": null
}
delimiter (string) optional

Delimiter to be used between ID elements.
Defaults to - (hyphen). Set to "" to use no delimiter at all.


Required: No

Default value: null

descriptor_formats (any) optional

Describe additional descriptors to be output in the descriptors output map.
Map of maps. Keys are names of descriptors. Values are maps of the form
\{<br/> format = string<br/> labels = list(string)<br/> \}
(Type is any so the map values can later be enhanced to provide additional options.)
format is a Terraform format string to be passed to the format() function.
labels is a list of labels, in order, to pass to format() function.
Label values will be normalized before being passed to format() so they will be
identical to how they appear in id.
Default is {} (descriptors output will be empty).


Required: No

Default value: { }

enabled (bool) optional

Set to false to prevent the module from creating any resources
Required: No

Default value: null

environment (string) optional

ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT'
Required: No

Default value: null

id_length_limit (number) optional

Limit id to this many characters (minimum 6).
Set to 0 for unlimited length.
Set to null for keep the existing setting, which defaults to 0.
Does not affect id_full.


Required: No

Default value: null

label_key_case (string) optional

Controls the letter case of the tags keys (label names) for tags generated by this module.
Does not affect keys of tags passed in via the tags input.
Possible values: lower, title, upper.
Default value: title.


Required: No

Default value: null

label_order (list(string)) optional

The order in which the labels (ID elements) appear in the id.
Defaults to ["namespace", "environment", "stage", "name", "attributes"].
You can omit any of the 6 labels ("tenant" is the 6th), but at least one must be present.


Required: No

Default value: null

label_value_case (string) optional

Controls the letter case of ID elements (labels) as included in id,
set as tag values, and output by this module individually.
Does not affect values of tags passed in via the tags input.
Possible values: lower, title, upper and none (no transformation).
Set this to title and set delimiter to "" to yield Pascal Case IDs.
Default value: lower.


Required: No

Default value: null

labels_as_tags (set(string)) optional

Set of labels (ID elements) to include as tags in the tags output.
Default is to include all labels.
Tags with empty values will not be included in the tags output.
Set to [] to suppress all generated tags.
Notes:
The value of the name tag, if included, will be the id, not the name.
Unlike other null-label inputs, the initial setting of labels_as_tags cannot be
changed in later chained modules. Attempts to change it will be silently ignored.


Required: No

Default value:

[
"default"
]
name (string) optional

ID element. Usually the component or solution name, e.g. 'app' or 'jenkins'.
This is the only ID element not also included as a tag.
The "name" tag is set to the full id string. There is no tag with the value of the name input.


Required: No

Default value: null

namespace (string) optional

ID element. Usually an abbreviation of your organization name, e.g. 'eg' or 'cp', to help ensure generated IDs are globally unique
Required: No

Default value: null

regex_replace_chars (string) optional

Terraform regular expression (regex) string.
Characters matching the regex will be removed from the ID elements.
If not set, "/[^a-zA-Z0-9-]/" is used to remove all characters other than hyphens, letters and digits.


Required: No

Default value: null

stage (string) optional

ID element. Usually used to indicate role, e.g. 'prod', 'staging', 'source', 'build', 'test', 'deploy', 'release'
Required: No

Default value: null

tags (map(string)) optional

Additional tags (e.g. {'BusinessUnit': 'XYZ'}).
Neither the tag keys nor the tag values will be modified by this module.


Required: No

Default value: { }

tenant (string) optional

ID element (Rarely used, not included by default). A customer identifier, indicating who this instance of a resource is for
Required: No

Default value: null

Outputs

codebuild_badge_url

The URL of the build badge when badge_enabled is enabled

codebuild_cache_bucket_arn

CodeBuild cache S3 bucket ARN

codebuild_cache_bucket_name

CodeBuild cache S3 bucket name

codebuild_project_id

CodeBuild project ID

codebuild_project_name

CodeBuild project name

codebuild_role_arn

CodeBuild IAM Role ARN

codebuild_role_id

CodeBuild IAM Role ID

codepipeline_arn

CodePipeline ARN

codepipeline_id

CodePipeline ID

Dependencies

Requirements

  • terraform, version: >= 1.3
  • aws, version: >= 5.0
  • random, version: >= 2.1

Providers

  • aws, version: >= 5.0
  • random, version: >= 2.1

Modules

NameVersionSourceDescription
codebuild2.0.1cloudposse/codebuild/awsn/a
github_webhook0.12.1cloudposse/repository-webhooks/githubn/a
this0.25.0cloudposse/label/nulln/a

Resources

The following resources are used by this module:

Data Sources

The following data sources are used by this module: