Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

aodn-devops-cicd #19

Closed
wants to merge 12 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions .github/workflows/build-image.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
name: Build Image cicd

on:
# push:
# branches:
# - devops-cicd
workflow_dispatch:

permissions:
id-token: write # JWT
contents: read # actions/checkout

jobs:
ogcapi_app_build:
runs-on: ubuntu-latest
environment: tfintegration
steps:
- name: Checkout Repo ogcapi
uses: actions/checkout@v4

- name: Set up QEMU Cross Platform Support
uses: docker/setup-qemu-action@v3

- name: Create Docker Buildx Worker
uses: docker/setup-buildx-action@v3

- name: Install JDK 17
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '17'
cache: 'maven'

- name: Build with Maven
run: mvn -B package --file pom.xml

- name: Set AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ vars.ROLE_ARN }}
role-session-name: GitHub_to_AWS_OIDC
aws-region: ${{ vars.AWS_REGION }}

- name: Login ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2

- name: Build and Push Application Image to ECR
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile
push: true
tags: ${{ vars.ECR_REPOSITORY }}:latest
76 changes: 76 additions & 0 deletions .github/workflows/deploy-staging.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
name: Deploy Dev cicd

on:
push:
branches:
- devops-cicd
workflow_dispatch:

permissions:
id-token: write
contents: read

jobs:
deploy_application:
runs-on: ubuntu-latest
environment: tfintegration
env:
tf_version: '1.5.7'
tg_version: '0.54.0'
tg_dir: './deploy/tg'

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ vars.ROLE_ARN }}
role-session-name: GitHub_OIDC
aws-region: ${{ vars.AWS_REGION }}

- name: Expose github environment as shell variables
env:
SECRETS_CONTEXT: ${{ toJson(secrets) }}
VARS_CONTEXT: ${{ toJson(vars) }}
run: |
EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64)
to_envs() { jq -r "to_entries[] | \"\(.key)<<$EOF\n\(.value)\n$EOF\n\""; }
echo "$VARS_CONTEXT" | to_envs >> $GITHUB_ENV
echo "$SECRETS_CONTEXT" | to_envs >> $GITHUB_ENV

- name: Install Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: ${{ env.tf_version }}

- name: Install Terragrunt
id: setup_terragrunt
run: |
wget https://github.com/gruntwork-io/terragrunt/releases/download/v${terragrunt_version}/terragrunt_linux_amd64 \
&& mv terragrunt_linux_amd64 terragrunt \
&& chmod +x terragrunt \
&& mv terragrunt /usr/local/bin/terragrunt
env:
terragrunt_version: ${{ env.tg_version }}

- name: Terragrunt Plan
id: terragrunt_plan
run: terragrunt plan -out=tf.plan
working-directory: ${{ env.tg_dir }}
env:
TF_INPUT: 0
TF_IN_AUTOMATION: true
# get the image digest from the build job with optional override from vars context
TF_VAR_image: ${{ vars.IMAGE || needs.build_push.outputs.image_digest }}

- name: Terragrunt Apply
id: terragrunt_apply
run: terragrunt apply -auto-approve tf.plan
working-directory: ${{ env.tg_dir }}
env:
TF_INPUT: 0
TF_IN_AUTOMATION: true
# get the image digest from the build job with optional override from vars context
TF_VAR_image: ${{ vars.IMAGE || needs.build_push.outputs.image_digest }}
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,8 @@
**/target/**/*
.idea
*.iml

**/.terraform/*
**/.terragrunt-cache/

.terraform.lock.hcl
12 changes: 12 additions & 0 deletions deploy/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
version: '3.7'

services:
terraform:
image: hashicorp/terraform:1.5.7
volumes:
- .:/infra
- ${HOME}/.aws:/root/.aws
working_dir: /infra
environment:
- AWS_PROFILE=${AWS_PROFILE}
command: []
18 changes: 18 additions & 0 deletions deploy/github/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Github Deployments
Deployment of this application uses [Github Deployment Environments](https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment).

A successful deployment relies on the correct variables being defined in order to deploy to the correct AWS account etc.

### Managing Environments
You can view the current environment settings by visiting https://github.com/aodn/sample-django-app/settings/environments.

You can view the currently defined variables there or from the cli using:
```bash
gh variable list -R aodn/sample-django-app -e staging
```

#### Updating Variables
Manually updating vars can be tedious and error-prone. Instead, you may define the variables you need as a .env file and push these values:
```bash
gh variable set -R aodn/sample-django-app -e staging -f staging.env
```
11 changes: 11 additions & 0 deletions deploy/github/production.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
ALB_PARAMETER_NAME=shared-alb-devops-sydney
APP_NAME=sample-django-app
AWS_ACCOUNT_ID=450356697252
AWS_REGION=ap-southeast-2
DB_NAME=api_prod
DB_USER=api_prod
ECR_PARAMETER_NAME=api
ECR_REGISTRY=450356697252.dkr.ecr.ap-southeast-2.amazonaws.com
ECR_REPOSITORY=api
ENVIRONMENT=production
RDS_PARAMETER_NAME=stefan-db/primary/evaluation
9 changes: 9 additions & 0 deletions deploy/github/staging.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
ALB_PARAMETER_NAME=shared-alb-devops-sydney
APP_NAME=sample-django-app
AWS_ACCOUNT_ID=450356697252
AWS_REGION=ap-southeast-2
ECR_PARAMETER_NAME=api
ECR_REGISTRY=450356697252.dkr.ecr.ap-southeast-2.amazonaws.com
ECR_REPOSITORY=api
ENVIRONMENT=staging
RDS_PARAMETER_NAME=stefan-db/primary/evaluation
37 changes: 37 additions & 0 deletions deploy/tf/alb.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
resource "aws_lb_target_group" "app" {
name = "${var.app_name}-${var.environment}"
port = 80
protocol = "HTTP"
target_type = "ip"
vpc_id = local.vpc_id

health_check {
enabled = true
path = "/health"
}
}

resource "aws_route53_record" "app" {
for_each = toset(var.app_hostnames)
zone_id = local.domain_zone_id
name = each.value
type = "CNAME"
ttl = 60
records = [var.alb_url]
}

resource "aws_lb_listener_rule" "app_fgate" {
for_each = toset(var.app_hostnames)
listener_arn = local.alb_https_listener_arn

action {
type = "forward"
target_group_arn = aws_lb_target_group.app.arn
}

condition {
host_header {
values = [aws_route53_record.app[each.value].fqdn]
}
}
}
2 changes: 2 additions & 0 deletions deploy/tf/aws_details.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
data "aws_caller_identity" "current" {}
data "aws_region" "current" {}
113 changes: 113 additions & 0 deletions deploy/tf/ecs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
locals {
# set container definition variables with default fallback values from ssm if available
app_vars = {}

app_container_vars = [for k, v in local.app_vars : { name = upper(k), value = v }]
# ecr_registry = split("/", local.ecr_repository_url)[0]
}

module "ecs" {
source = "terraform-aws-modules/ecs/aws"
version = "~> 5.7.0"

# Cluster Configuration
cluster_name = "${var.app_name}-${var.environment}"
cluster_configuration = {
name = "containerInsights"
value = "enabled"
}
create_task_exec_iam_role = true
fargate_capacity_providers = {
FARGATE = {
default_capacity_provider_strategy = {
weight = 50
}
}
FARGATE_SPOT = {
default_capacity_provider_strategy = {
weight = 50
}
}
}

# Service Configuration
services = {

"${var.app_name}-${var.environment}" = {
capacity_provider_strategy = {
dedicated = {
base = 0
capacity_provider = "FARGATE"
weight = 100
}
# spot = {
# base = 0
# capacity_provider = "FARGATE_SPOT"
# weight = 100
# }
}

# allow ECS exec commands on containers (e.g. to get a shell session)
enable_execute_command = true

# resources
cpu = 512
memory = 1024

# wait for service to reach steady state
wait_for_steady_state = true

# Container definition(s)
container_definitions = {
app = {
name = var.container_name
image = "450356697252.dkr.ecr.ap-southeast-4.amazonaws.com/ogcapi:latest"
health_check = {}
readonly_root_filesystem = false
essential = true
memory_reservation = 256
environment = local.app_container_vars
port_mappings = [
{
name = var.container_name
containerPort = 80
hostPort = 80
}
]
}
}

deployment_circuit_breaker = {
enable = true
rollback = true
}

load_balancer = {
service = {
target_group_arn = aws_lb_target_group.app.arn
container_name = var.container_name
container_port = var.container_port
}
}

subnet_ids = local.private_subnets

security_group_rules = {
ingress_vpc = {
type = "ingress"
from_port = var.container_port
to_port = var.container_port
protocol = "tcp"
cidr_blocks = [local.vpc_cidr]
}
egress_all = {
type = "egress"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
}
}
}
Loading