Skip to content

Commit

Permalink
Feature/infra as code (#831)
Browse files Browse the repository at this point in the history
  • Loading branch information
sburba committed Oct 17, 2021
1 parent 7450c05 commit 2162c4f
Show file tree
Hide file tree
Showing 17 changed files with 700 additions and 133 deletions.
158 changes: 95 additions & 63 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,60 @@ orbs:
heroku: circleci/heroku@1.2.6
executors:
web-executor:
resource_class: medium
docker:
- image: cimg/node:14.17.3
- image: cimg/node:14.17.6
e2e-executor:
docker:
- image: mcr.microsoft.com/playwright:focal
terraform-executor:
docker:
- image: hashicorp/terraform:1.0.8
commands:
build_web:
parameters:
api_domain:
type: string
description: ttbud backend API domain
steps:
- install_yarn_deps:
cache_prefix: web
- run:
name: Build
environment:
REACT_APP_DOMAIN: << parameters.api_domain >>
REACT_APP_API_WEBSOCKET_PORT: 443
command: yarn build
- run:
name: Package
command: tar -czvf /tmp/ttbud-web.tar.gz --directory=build .
- store_artifacts:
path: /tmp/ttbud-web.tar.gz
destination: ttbud-web.tar.gz
- run:
name: Save build tarball URL
command: ../infra/get_ci_artifact $CIRCLE_BUILD_NUM ttbud-web.tar.gz > /tmp/web-tarball-url
- persist_to_workspace:
root: /tmp
paths:
- web-tarball-url
release:
parameters:
workspace:
type: string
description: Terraform workspace to deploy
steps:
- attach_workspace:
at: /tmp/workspace
- run:
name: Apply Release
environment:
DEPLOY_WORKSPACE: << parameters.workspace >>
command: |
DEPLOY_COMMIT_HASH="$CIRCLE_SHA1" \
DEPLOY_TF_TOKEN="$TERRAFORM_TOKEN" \
DEPLOY_WEB_TARBALL_URL="$(cat /tmp/workspace/web-tarball-url)" \
DEPLOY_API_TARBALL_URL="https://api.github.com/repos/ttbud/ttbud/tarball/${CIRCLE_SHA1}" \
./do_deploy
install_yarn_deps:
description: "Install all yarn dependencies"
parameters:
Expand All @@ -29,35 +76,6 @@ commands:
key: << parameters.cache_prefix >>-deps-v5-{{ checksum "yarn.lock" }}
paths:
- node_modules
release_web:
parameters:
target_name:
type: string
site_id:
type: env_var_name
steps:
- checkout:
path: ~/repo
- install_yarn_deps:
cache_prefix: web
- run:
name: Build Bundle
command: yarn build
- run:
name: Release to << parameters.target_name >>
command: web/node_modules/.bin/netlify deploy --site $<< parameters.site_id >> --auth $NETLIFY_AUTH_TOKEN --prod
working_directory: ~/repo
release_api:
parameters:
app_name:
type: string
steps:
- checkout
- heroku/install
- heroku/deploy-via-git:
app-name: << parameters.app_name >>
# Bors force pushes to the staging branch for each build, so we have to push force to heroku
force: true
jobs:
api:
docker:
Expand Down Expand Up @@ -125,36 +143,47 @@ jobs:
command: yarn run test --reporters=default --reporters=jest-junit --maxWorkers=2
- store_test_results:
path: test-results
release-staging-web:
build-staging-web:
executor: web-executor
working_directory: ~/repo/web
environment:
REACT_APP_DOMAIN: ttbud-staging.herokuapp.com
REACT_APP_API_WEBSOCKET_PORT: 443
steps:
- release_web:
target_name: Staging
site_id: NETLIFY_STAGING_SITE_ID
release-prod-web:
- checkout:
path: ~/repo
- build_web:
api_domain: ttbud-staging.herokuapp.com
build-prod-web:
executor: web-executor
working_directory: ~/repo/web
environment:
REACT_APP_DOMAIN: ttbud-prod.herokuapp.com
REACT_APP_API_WEBSOCKET_PORT: 443
steps:
- release_web:
target_name: Prod
site_id: NETLIFY_PROD_SITE_ID
release-staging-api:
executor: heroku/default
- checkout:
path: ~/repo
- build_web:
api_domain: ttbud-prod.herokuapp.com
release-staging:
executor: terraform-executor
working_directory: ~/repo/infra
steps:
- release_api:
app_name: ttbud-staging
release-prod-api:
executor: heroku/default
- checkout:
path: ~/repo
- release:
workspace: staging
release-prod:
executor: terraform-executor
working_directory: ~/repo/infra
steps:
- release_api:
app_name: ttbud-prod
- checkout:
path: ~/repo
- release:
workspace: prod
terraform-lint:
executor: terraform-executor
working_directory: ~/repo/infra
steps:
- checkout:
path: ~/repo
- run:
name: Check Style
command: terraform fmt -check -recursive
e2e-lint:
executor: e2e-executor
working_directory: ~/repo/e2e
Expand Down Expand Up @@ -210,31 +239,34 @@ workflows:
<<: *DEFAULT_FILTER
- e2e-lint:
<<: *DEFAULT_FILTER
- release-staging-web:
requires:
- web
- terraform-lint:
<<: *DEFAULT_FILTER
- build-staging-web:
filters:
branches:
only:
- staging
- trying
- release-staging-api:
- release-staging:
requires:
- web
- api
- build-staging-web
filters:
branches:
only:
- staging
- trying
- staging
- trying
- e2e-staging:
requires:
- release-staging-api
- release-staging-web
- release-prod-web:
- release-staging
- build-prod-web:
filters:
branches:
only: master
- release-prod-api:
- release-prod:
requires:
- build-prod-web
filters:
branches:
only: master
72 changes: 7 additions & 65 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,16 @@ We made TTBud so we can play DnD with our friends across the globe. It's a repla
Try it out here:
[ttbud.app](https://ttbud.app)

## Requirements

## Development

### Requirements

- [mkcert](https://github.com/FiloSottile/mkcert)
- [docker](https://docs.docker.com/v17.09/engine/installation/)
- [docker-compose](https://docs.docker.com/compose/install/)

## Development

### Setup
```bash
# Create a dev ssl cert
mkcert -install
Expand All @@ -28,9 +30,9 @@ echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo s

# Configure your environment
cp .env.example .env
# Build all the images
# Build all the images (Needs to re-run each time api dependencies change)
docker-compose build
# Install web dependencies
# Install web dependencies (Needs to re-run each time web dependencies change)
docker-compose run --rm web yarn install
# Start the development server in the background
docker-compose up -d
Expand Down Expand Up @@ -81,66 +83,6 @@ docker-compose run --rm api pytest --cov=src --cov-report=html tests
docker-compose run --rm web yarn test
```

## Infrastructure setup

### Requirements

- [heroku cli](https://devcenter.heroku.com/articles/heroku-cli#download-and-install)
- [netlify cli](https://docs.netlify.com/cli/get-started/#installation)

### S3 Setup

- Make ttbud-prod and ttbud-staging buckets
- Create one IAM user for each bucket with access key credentials
- Add an inline policy to allow each user ListBucket, GetObject, PutObject, and DeleteObject permissions for the appropriate bucket and all objects

### API

```bash
heroku update beta
heroku plugins:install @heroku-cli/plugin-manifest

# Create staging environment
heroku apps:create ttbud-staging --manifest --remote staging
heroku config:set ENVIRONMENT=staging --remote staging
heroku config:set JSON_LOGS=true --remote staging
heroku config:set BYPASS_RATE_LIMIT_KEY=$(uuidgen) --remote staging
heroku config:set REDIS_SSL_VALIDATION=self_signed --remote staging
heroku config:set AWS_KEY_ID=<staging_key_id> --remote staging
heroku config:set AWS_SECRET_KEY=<staging_secret_key> --remote staging
heroku config:set AWS_REGION=<aws_region> --remote staging
heroku config:set AWS_BUCKET=<staging_bucket_name> --remote staging

# Create prod environment
heroku apps:create ttbud --manifest --remote prod
heroku config:set ENVIRONMENT=prod --remote prod
heroku config:set JSON_LOGS=true --remote prod
heroku config:set BYPASS_RATE_LIMIT_KEY=$(uuidgen) --remote prod
heroku config:set REDIS_SSL_VALIDATION=self_signed --remote prod
heroku config:set AWS_KEY_ID=<prod_key_id> --remote prod
heroku config:set AWS_SECRET_KEY=<prod_secret_key> --remote prod
heroku config:set AWS_REGION=<aws_region> --remote prod
heroku config:set AWS_BUCKET=<prod_bucket_name> --remote prod
```

### Web

```bash
netlify sites:create -n ttbud
netlify sites:create -n ttbud-staging
```

### CI

Connect circleci to the github repository

Set up the following API keys:

- `HEROKU_API_KEY`: An API key that has access to your heroku apps
- `NETLIFY_AUTH_TOKEN`: An API key that has access to your Netlify sites
- `NETLIFY_STAGING_SITE_ID`: The site id returned when creating the staging Netlify site above
- `NETLIFY_PROD_SITE_ID`: The site id returned when creating the prod Netlify site above

## Licenses

- icons in web/src/icon - Licensed from [game-icons.net](https://game-icons.net) under [CC BY 3.0](https://creativecommons.org/licenses/by/3.0/)
Expand Down
6 changes: 4 additions & 2 deletions bors.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ status = [
"ci/circleci: api",
"ci/circleci: web",
"ci/circleci: e2e-lint",
"ci/circleci: release-staging-web",
"ci/circleci: release-staging-api",
"ci/circleci: terraform-lint",
"ci/circleci: release-staging",
"ci/circleci: e2e-staging",
]
# 30 minute timeout
timeout_sec = 1800
use_squash_merge = true
required_approvals = 1
delete_merged_branches = true
3 changes: 0 additions & 3 deletions heroku.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
setup:
addons:
- plan: timber-logging:free
build:
docker:
web: api/Dockerfile
4 changes: 4 additions & 0 deletions infra/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.terraform

# Automatically generated at build time to specify deploy config
deploy.auto.tfvars

0 comments on commit 2162c4f

Please sign in to comment.