Skip to content
This repository has been archived by the owner on Feb 22, 2024. It is now read-only.

Commit

Permalink
initial terraform deployment
Browse files Browse the repository at this point in the history
  • Loading branch information
AnatoleAM committed Dec 2, 2023
1 parent 02c3adc commit 544f68a
Show file tree
Hide file tree
Showing 7 changed files with 275 additions and 50 deletions.
137 changes: 87 additions & 50 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: CD Lint, Build, Test, Deploy
name: CompactDisc Lint, Build, Test, Deploy

on:
push:
Expand All @@ -14,26 +14,27 @@ on:
workflow_dispatch:
inputs:
deploy:
description: "Deploy location"
description: "Which environment to deploy to"
required: true
default: "none"
type: choice
options:
- production
- staging
- prod
- test
- none

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

env:
DEPLOY: ${{ (inputs.deploy != 'none' && inputs.deploy) || ((github.event_name == 'workflow_dispatch' && github.event.inputs.deploy == 'prod') || (github.event_name == 'push' && github.ref_type == 'branch' && github.ref_name == 'master') && 'prod') || ((github.event_name == 'workflow_dispatch' && github.event.inputs.deploy == 'test') || (github.event_name == 'push' && github.ref_type == 'branch' && github.ref_name == 'dev' && 'test') || (github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'staged')) && 'test') || 'none' }}

jobs:
ci:
name: CD Lint, Build, Test, Deploy
name: CompactDisc Lint, Build, Test, Deploy
runs-on: aws-runner
env:
DEPLOY_PROD: ${{ (github.event_name == 'workflow_dispatch' && github.event.inputs.deploy == 'production') || (github.event_name == 'push' && github.ref_type == 'branch' && github.ref_name == 'master') }}
DEPLOY_STAGE: ${{ (github.event_name == 'workflow_dispatch' && github.event.inputs.deploy == 'staging') || (github.event_name == 'push' && github.ref_type == 'branch' && github.ref_name == 'dev') || (github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'staged')) }}
GOLANGCI_LINT_CACHE: /home/runner/.cache/golangci-lint
concurrency:
group: ${{ github.workflow }}-ci-${{ github.ref }}
Expand All @@ -43,7 +44,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: 1.18.3
go-version: 1.18

- uses: actions/setup-node@v3
with:
Expand All @@ -59,8 +60,8 @@ jobs:

- id: cache-paths
run: |
echo "::set-output name=go-build::$(go env GOCACHE)"
echo "::set-output name=go-mod::$(go env GOMODCACHE)"
echo "go-build=$(go env GOCACHE)" >> $GITHUB_OUTPUT
echo "go-mod=$(go env GOMODCACHE)" >> $GITHUB_OUTPUT
- name: Go Build Cache
uses: actions/cache@v3
Expand All @@ -86,6 +87,9 @@ jobs:
path: node_modules
key: ${{ runner.os }}-node_modules-${{ hashFiles('yarn.lock') }}

- name: Make
run: sudo apt-get install make

- name: Install Dependencies
run: make deps

Expand All @@ -101,64 +105,97 @@ jobs:
- name: Build App
run: make build

- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
if: ${{ env.DEPLOY_PROD == 'true' || env.DEPLOY_STAGE == 'true' }}
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ secrets.AWS_REGION }}

- name: Login to Amazon ECR
id: login-ecr
if: ${{ env.DEPLOY_PROD == 'true' || env.DEPLOY_STAGE == 'true' }}
uses: aws-actions/amazon-ecr-login@v1

- name: Make build context
if: ${{ env.DEPLOY_PROD == 'true' || env.DEPLOY_STAGE == 'true' }}
if: env.DEPLOY != 'none'
run: |
docker context create builders
- name: Setup buildx
uses: docker/setup-buildx-action@v2
if: ${{ env.DEPLOY_PROD == 'true' || env.DEPLOY_STAGE == 'true' }}
if: env.DEPLOY != 'none'
with:
install: true
endpoint: builders

- name: Login to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ github.token }}

- name: Build docker image
uses: docker/build-push-action@v3
if: ${{ env.DEPLOY_PROD == 'true' || env.DEPLOY_STAGE == 'true' }}
uses: docker/build-push-action@v4
if: env.DEPLOY != 'none'
with:
context: .
file: docker/partial.Dockerfile
# cache-from: |
# type=registry,ref=gha
# cache-to: |
# type=registry,ref=gha,mode=max
tags: |
${{ steps.login-ecr.outputs.registry }}/${{ (env.DEPLOY_PROD == 'true' && '7tv') || '7tv-stage' }}/compactdisc:latest
${{ steps.login-ecr.outputs.registry }}/${{ (env.DEPLOY_PROD == 'true' && '7tv') || '7tv-stage' }}/compactdisc:${{ github.sha }}
ghcr.io/seventv/compactdisc:${{ env.DEPLOY }}-${{ github.sha }}
ghcr.io/seventv/compactdisc:${{ env.DEPLOY }}-latest
push: true

- name: Update deployment template
uses: danielr1996/envsubst-action@1.1.0
if: ${{ env.DEPLOY_PROD == 'true' || env.DEPLOY_STAGE == 'true' }}
env:
IMAGE: ${{ steps.login-ecr.outputs.registry }}/${{ (env.DEPLOY_PROD == 'true' && '7tv') || '7tv-stage' }}/compactdisc:${{ github.sha }}
with:
input: k8s/${{ (env.DEPLOY_PROD == 'true' && 'production') || 'staging' }}.template.yaml
output: k8s/deploy.yaml
validate:
name: CompactDisc Deploy Validation
needs: ci
runs-on: ubuntu-latest
permissions:
pull-requests: write
defaults:
run:
working-directory: ./terraform

- name: Setup Kubectl
uses: azure/setup-kubectl@v3.0
steps:
- name: Checkout code
id: ok
if: env.DEPLOY != 'none'
uses: actions/checkout@v3

- name: Deploy to k8s
if: ${{ env.DEPLOY_PROD == 'true' || env.DEPLOY_STAGE == 'true' }}
- name: "Setup Terraform"
if: steps.ok.outcome == 'success'
uses: hashicorp/setup-terraform@v1
with:
cli_config_credentials_token: ${{ secrets.TF_API_TOKEN }}

- name: "Terraform Init"
if: steps.ok.outcome == 'success'
id: init
env:
KUBE_CONFIG_DATA: ${{ (env.DEPLOY_PROD == 'true' && secrets.KUBECONFIG) || secrets.KUBECONFIG_STAGE }}
TF_WORKSPACE: ${{ env.DEPLOY }}
run: terraform init
continue-on-error: true

- name: "Terraform Workspace"
if: steps.ok.outcome == 'success'
run: terraform workspace select -or-create=true ${{ env.DEPLOY }}

- name: Terraform fmt
if: steps.ok.outcome == 'success'
id: fmt
run: terraform fmt -check
continue-on-error: true

- name: Terraform Validate
if: steps.ok.outcome == 'success'
id: validate
run: terraform validate -no-color

- name: Terraform Variables
if: steps.ok.outcome == 'success'
run: |
mkdir -p ~/.kube
(echo $KUBE_CONFIG_DATA | base64 -d) >> ~/.kube/config
kubectl apply -f k8s/deploy.yaml
cat <<EOF > *.auto.tfvars
image_url="ghcr.io/seventv/compactdisc:${{ env.DEPLOY }}-${{ github.sha }}"
image_pull_policy="IfNotPresent"
EOF
- name: "Terraform Plan"
if: steps.ok.outcome == 'success'
id: plan
run: terraform plan -no-color

- name: "Terraform Apply"
if: steps.ok.outcome == 'success'
id: apply
run: terraform apply -no-color -auto-approve
continue-on-error: true
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@ out/

go.work*
config.yaml

terraform/.*
38 changes: 38 additions & 0 deletions terraform/config.template.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Log level
level: info

discord:
guild_id: ${discord_guild_id}
default_role_id: ${discord_default_role_id}
token: ${discord_bot_token}
channels:
activity_feed: ${ch_activity_feed}
mod_logs: ${ch_mod_logs}
mod_actor_tracker: ${ch_mod_actor_tracker}
events: ${ch_events}

http:
addr: "0.0.0.0"
port: 3000

# MongoDB Settings
mongo:
uri: ${mongo_uri}
db: ${mongo_db}
username: ${mongo_username}
password: ${mongo_password}
direct: false

# Redis Settings
redis:
addresses:
- redis-node-0.redis-headless.database.svc.cluster.local:26379
- redis-node-1.redis-headless.database.svc.cluster.local:26379
- redis-node-2.redis-headless.database.svc.cluster.local:26379
- redis-node-3.redis-headless.database.svc.cluster.local:26379
- redis-node-4.redis-headless.database.svc.cluster.local:26379
sentinel: true
master_name: "mymaster"
username: ${redis_username}
password: ${redis_password}
database: 0
30 changes: 30 additions & 0 deletions terraform/deployment.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
data "kubernetes_namespace" "app" {
metadata {
name = var.namespace
}
}

resource "kubernetes_secret" "app" {
metadata {
name = "api"
namespace = var.namespace
}

data = {
"config.yaml" = templatefile("${path.module}/config.template.yaml", {
guild_id = var.discord_guild_id
default_role_id = var.discord_default_role_id
token = var.discord_bot_token
ch_activity_feed = "817375925271527449"
ch_mod_logs = "989251544165777450"
ch_mod_actor_tracker = "1080982942156869743"
ch_events = "1015281319758004335"
mongo_uri = local.infra.mongodb_uri
mongo_username = local.infra.mongodb_user_app.username
mongo_password = local.infra.mongodb_user_app.password
mongo_database = "7tv"
redis_username = "default"
redis_password = local.infra.redis_password
})
}
}
16 changes: 16 additions & 0 deletions terraform/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
terraform {
backend "remote" {
hostname = "app.terraform.io"
organization = "7tv"

workspaces {
prefix = "seventv-compactdisc-"
}
}
}

locals {
infra_workspace_name = replace(terraform.workspace, "compactdisc", "infra")
infra = data.terraform_remote_state.infra.outputs
image_url = var.image_url != null ? var.image_url : format("ghcr.io/seventv/compactdisc:%s-latest", trimprefix(terraform.workspace, "seventv-compactdisc-"))
}
47 changes: 47 additions & 0 deletions terraform/providers.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.7.0"
}

kubernetes = {
source = "hashicorp/kubernetes"
version = "2.18.1"
}

random = {
source = "hashicorp/random"
}

kubectl = {
source = "gavinbunney/kubectl"
version = "1.14.0"
}
}
}

provider "aws" {
region = var.region
}

provider "kubernetes" {
host = data.aws_eks_cluster.cluster.endpoint
token = data.aws_eks_cluster_auth.cluster.token
cluster_ca_certificate = base64decode(data.aws_eks_cluster.cluster.certificate_authority.0.data)
}

provider "kubectl" {
host = data.aws_eks_cluster.cluster.endpoint
token = data.aws_eks_cluster_auth.cluster.token
cluster_ca_certificate = base64decode(data.aws_eks_cluster.cluster.certificate_authority.0.data)
load_config_file = false
}

data "aws_eks_cluster" "cluster" {
name = local.infra_workspace_name
}

data "aws_eks_cluster_auth" "cluster" {
name = local.infra_workspace_name
}
Loading

0 comments on commit 544f68a

Please sign in to comment.