Skip to content

Latest commit

 

History

History
157 lines (123 loc) · 5.56 KB

README.md

File metadata and controls

157 lines (123 loc) · 5.56 KB

Terraform AWS S3 CI

Reusable Terraform modules for continuous integration of static web applications deployed on s3 and served by cloudfront.

Components

  • Release CI: CI/CD pipeline to deploy static web applications to S3 Bucket.

  • Preview CI: CD/CD build to deploy static web application feature branches to a preview S3 Bucket.

Features

✅ Support for mono repositories, by providing the ability to change the base directory using app_base_dir variable.

✅ Supports any package manager, you only need to specify the installation command to use for fetching dependencies, i.e. yarn install or npm install using the Terraform variable app_install_cmd

✅ Ability to change the build command using the Terraform variable app_build_cmd.

✅ Supports any static web application framework (React, Gatsby, VueJS), you only need to provide the build folder to be deployed using the app_build_dir, for example build for react and public for gatsby.

✅ Ability to change the runtime node version using the app_node_version Terraform variable.

✅ Trigger the release pipeline based on pushes to Github branches or based on tag publish events by setting the Terraform variable pre_release to false or true.

✅ Support custom DOT ENV variables by leveraging AWS Secrets Manager. the pipeline will output envs_sm_id that you can use to update the secrets' manager secret version.

✅ On each started, succeeded and failed event, the pipeline can send notifications to the target Slack channels provided by ci_notifications_slack_channels Terraform variable.

✅ To improve the performance of the builds and speed up the subsequent runs, the pipeline can cache the node modules to a remote S3 artifacts bucket s3_artifacts at the end of the builds and pull the cached node modules at the start of each build.

✅ After a successful deployment, the pipeline will use the cloudfront_distribution_id to invalidate the old web application files from the edge cache. The next time a viewer requests the web application, CloudFront returns to the origin to fetch the latest version of the application.

✅ Notify the preview build completion and the preview URL to Github users by commenting on the target PR that triggered the Build.

Usage

  • Preview CI Build
module "webapp_preview_ci" {
  source      = "git::https://github.com/obytes/terraform-aws-s3-ci//modules/webapp-preview"
  prefix      = local.prefix
  common_tags = local.common_tags

  # Artifacts
  s3_artifacts = {
    arn    = aws_s3_bucket.artifacts.arn
    bucket = aws_s3_bucket.artifacts.bucket
  }

  # Github
  github = {
    owner          = "obytes"
    token          = "Token used to comment on github PRs when the preview is ready!"
    webhook_secret = "not-secret"
  }
  pre_release     = false
  repository_name = "react-typescript-starter"

  # Build
  app_base_dir     = "."
  app_build_dir    = "build"
  app_node_version = "latest"
  app_install_cmd  = "yarn install"
  app_build_cmd    = "yarn build"

  # Web & Cloudfront (The used CDN module is here https://github.com/obytes/terraform-aws-s3-cdn)
  s3_web                     = module.webapp_preview_cdn.s3         
  cloudfront_distribution_id = module.webapp_preview_cdn.dist["id"]

  # Notification
  ci_notifications_slack_channels = {
    info  = "ci-info"
    alert = "ci-alert"
  }
}

# Better to not manage this resource with terraform 
# and let users modify secrets directly from console.
resource "aws_secretsmanager_secret_version" "webapp_preview_env_vars" {
  secret_id     = module.webapp_preview_ci.envs_sm_id
  secret_string = jsonencode({
    REACT_APP_FIREBASE_API_KEY        = "REACT_APP_FIREBASE_API_KEY"
    REACT_APP_FIREBASE_PROJECT_ID     = "REACT_APP_FIREBASE_PROJECT_ID"
    REACT_APP_FIREBASE_AUTH_DOMAIN    = "REACT_APP_FIREBASE_AUTH_DOMAIN"
    REACT_APP_FIREBASE_MEASUREMENT_ID = "REACT_APP_FIREBASE_MEASUREMENT_ID"
  })
}
  • Release CI Pipeline
module "webapp_release_ci" {
  source      = "git::https://github.com/obytes/terraform-aws-s3-ci//modules/webapp-release"
  prefix      = local.prefix
  common_tags = local.common_tags

  # Artifacts
  s3_artifacts = {
    arn    = aws_s3_bucket.artifacts.arn
    bucket = aws_s3_bucket.artifacts.bucket
  }

  # Github
  github = {
    owner          = "obytes"
    webhook_secret = "not-secret"
    connection_arn = "arn:aws:codestar-connections:us-east-1:{ACCOUNT_ID}:connection/{CONNECTION_ID}"
  }
  pre_release       = false
  github_repository = {
    name   = "react-typescript-starter"
    branch = "main"
  }

  # Build
  app_base_dir     = "."
  app_build_dir    = "build"
  app_node_version = "latest"
  app_install_cmd  = "yarn install"
  app_build_cmd    = "yarn build"

  # Web & Cloudfront (The used CDN module is here https://github.com/obytes/terraform-aws-s3-cdn)
  s3_web                     = module.webapp_main_cdn.s3         
  cloudfront_distribution_id = module.webapp_main_cdn.dist["id"]

  # Notification
  ci_notifications_slack_channels = {
    info  = "ci-info"
    alert = "ci-alert"
  }
}

# Better to not manage this resource with terraform 
# and let users modify secrets directly from console.
resource "aws_secretsmanager_secret_version" "webapp_release_env_vars" {
  secret_id     = module.webapp_release_ci.envs_sm_id
  secret_string = jsonencode({
    REACT_APP_FIREBASE_API_KEY        = "REACT_APP_FIREBASE_API_KEY"
    REACT_APP_FIREBASE_PROJECT_ID     = "REACT_APP_FIREBASE_PROJECT_ID"
    REACT_APP_FIREBASE_AUTH_DOMAIN    = "REACT_APP_FIREBASE_AUTH_DOMAIN"
    REACT_APP_FIREBASE_MEASUREMENT_ID = "REACT_APP_FIREBASE_MEASUREMENT_ID"
  })
}