Skip to content

Commit e9f6dfc

Browse files
authored
fix: isolate dev, ci, prod environemnts; consolidate secrets (#1215)
* fix: isolate dev, ci, prod environemnts; consolidate secrets * fix(settings): always define settings environment * fix: pylint
1 parent 949a933 commit e9f6dfc

File tree

14 files changed

+231
-277
lines changed

14 files changed

+231
-277
lines changed

.env.example

Lines changed: 39 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,39 @@
1-
# Django
2-
DJANGO_SETTINGS_MODULE=?
3-
DEBUG=?
4-
SECRET_KEY=?
5-
6-
ENVIRONMENT=?
7-
8-
# review drive account
9-
REVIEW_DRIVE_ID=?
10-
REVIEW_DRIVE_EMAIL=?
11-
REVIEW_DRIVE_PASSWORD=?
12-
13-
# local database
14-
DB_NAME=?
15-
DB_USER=?
16-
DB_PASSWORD=?
17-
DB_HOST=?
18-
DB_PORT=?
19-
20-
# prod database
21-
PROD_DB_NAME=?
22-
PROD_DB_USER=?
23-
PROD_DB_PASSWORD=?
24-
PROD_DB_HOST=?
25-
PROD_DB_PORT=?
26-
27-
# feedback
28-
EMAIL_HOST_USER=?
29-
EMAIL_HOST_PASSWORD=?
30-
31-
# aws
32-
AWS_ACCESS_KEY_ID=?
33-
AWS_SECRET_ACCESS_KEY=?
34-
35-
# s3
36-
AWS_STORAGE_BUCKET_NAME=?
37-
AWS_S3_REGION_NAME=?
38-
39-
# cognito
40-
COGNITO_USER_POOL_ID=?
41-
COGNITO_APP_CLIENT_ID=?
42-
COGNITO_APP_CLIENT_SECRET=?
43-
COGNITO_DOMAIN=?
44-
COGNITO_REGION_NAME=?
45-
46-
# ec2
47-
EC2_USER=?
48-
EC2_HOST=?
49-
PEM_KEY=?
1+
# =============================================================================
2+
# REQUIRED FOR ALL ENVIRONMENTS
3+
# =============================================================================
4+
SECRET_KEY=any-random-string
5+
6+
# =============================================================================
7+
# LOCAL DEVELOPMENT (docker-compose, local_dump.sh, reset-db.sh)
8+
# =============================================================================
9+
DB_NAME=tcf_db
10+
DB_USER=tcf_django
11+
DB_PASSWORD=s3kr1t
12+
DB_HOST=tcf_db
13+
DB_PORT=5432
14+
15+
# =============================================================================
16+
# OPTIONAL - For auth features (login/logout/profile)
17+
# =============================================================================
18+
# COGNITO_USER_POOL_ID=
19+
# COGNITO_APP_CLIENT_ID=
20+
# COGNITO_APP_CLIENT_SECRET=
21+
# COGNITO_DOMAIN=
22+
# COGNITO_REGION_NAME=us-east-1
23+
24+
# =============================================================================
25+
# OPTIONAL - For prod_dump.sh script (must activate EC2 instances & get pem key)
26+
# =============================================================================
27+
# EC2_HOST=
28+
# EC2_USER=
29+
# PEM_KEY=path/to/your/key.pem
30+
# PROD_DB_HOST=
31+
# PROD_DB_USER=
32+
# PROD_DB_PASSWORD=
33+
34+
# =============================================================================
35+
# OPTIONAL - For load_review_drive management command
36+
# =============================================================================
37+
# REVIEW_DRIVE_ID=
38+
# REVIEW_DRIVE_EMAIL=
39+
# REVIEW_DRIVE_PASSWORD=

.github/workflows/aws.yml

Lines changed: 9 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,76 +1,30 @@
1-
# Based on https://github.com/actions/starter-workflows/blob/main/ci/django.yml
1+
# AWS ECS Deployment Workflow
22
name: AWS Deployment
33

44
on:
5-
# CI must pass on the master branch
65
workflow_run:
76
workflows: ["Continuous Integration"]
87
branches: [master]
98
types:
109
- completed
1110

1211
env:
13-
PYTHON_TARGET: 3.11
14-
# Django
15-
DJANGO_SETTINGS_MODULE: tcf_core.settings.prod
16-
SECRET_KEY: ${{ secrets.SECRET_KEY }}
17-
DEBUG: 0
18-
ENVIRONMENT: production
19-
# database
20-
AWS_RDS_NAME: ${{ secrets.AWS_RDS_NAME }}
21-
AWS_RDS_USER: ${{ secrets.AWS_RDS_USER }}
22-
AWS_RDS_PASSWORD: ${{ secrets.AWS_DS_PASSWORD }}
23-
AWS_RDS_HOST: ${{ secrets.AWS_RDS_HOST }}
24-
AWS_RDS_PORT: ${{ secrets.AWS_RDS_PORT }}
25-
# AWS Cognito
26-
COGNITO_USER_POOL_ID: ${{ secrets.COGNITO_USER_POOL_ID }}
27-
COGNITO_APP_CLIENT_ID: ${{ secrets.COGNITO_APP_CLIENT_ID }}
28-
COGNITO_APP_CLIENT_SECRET: ${{ secrets.COGNITO_APP_CLIENT_SECRET }}
29-
COGNITO_DOMAIN: ${{ secrets.COGNITO_DOMAIN }}
30-
COGNITO_REGION_NAME: ${{ secrets.COGNITO_REGION_NAME }}
31-
# email for account verification
32-
EMAIL_HOST_USER: ${{ secrets.EMAIL_HOST_USER }}
33-
EMAIL_HOST_PASSWORD: ${{ secrets.EMAIL_HOST_PASSWORD }}
34-
# review drive account information
35-
REVIEW_DRIVE_ID: ${{ secrets.REVIEW_DRIVE_ID }}
36-
REVIEW_DRIVE_EMAIL: ${{ secrets.REVIEW_DRIVE_EMAIL }}
37-
REVIEW_DRIVE_PASSWORD: ${{ secrets.REVIEW_DRIVE_PASSWORD }}
38-
# aws ecs image
3912
AWS_REGION: us-east-1
4013
ECS_SERVICE: barrett-fogle-love-v1
4114
ECS_CLUSTER: tcf-fargate-cluster
4215
ECR_REPO: tcf/thecourseforum2
4316
ECR_CONTAINER_NAME: tcf-container
44-
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
45-
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
46-
AWS_ACCOUNT_ID: ${{ secrets.AWS_ACCOUNT_ID }}
47-
AWS_STORAGE_BUCKET_NAME: ${{ secrets.AWS_STORAGE_BUCKET_NAME }}
48-
AWS_S3_CUSTOM_DOMAIN: ${{ secrets.AWS_S3_CUSTOM_DOMAIN }}
4917

5018
jobs:
5119
deploy:
52-
# if: ${{ github.event.workflow_run.conclusion == 'success' }}
20+
if: ${{ github.event.workflow_run.conclusion == 'success' }}
5321
runs-on: ubuntu-latest
5422
steps:
55-
- name: Checkout `master`
23+
- name: Checkout master
5624
uses: actions/checkout@v4
5725
with:
5826
ref: ${{ github.event.workflow_run.head_sha }}
5927

60-
- name: Set up Python ${{ env.PYTHON_TARGET }}
61-
uses: actions/setup-python@v5
62-
with:
63-
python-version: ${{ env.PYTHON_TARGET }}
64-
cache: 'pip'
65-
66-
- name: Install Python packages
67-
run: |
68-
python -m pip install --upgrade pip
69-
pip install django django-environ django-storages boto3 django-cachalot djangorestframework django-filter psycopg2-binary
70-
71-
- name: Collect static files
72-
run: python manage.py collectstatic --no-input
73-
7428
- name: Configure AWS credentials
7529
uses: aws-actions/configure-aws-credentials@v4
7630
with:
@@ -79,38 +33,37 @@ jobs:
7933
aws-region: ${{ env.AWS_REGION }}
8034

8135
- name: Login to Amazon ECR
82-
id: login-ecr
8336
uses: aws-actions/amazon-ecr-login@v2
8437

8538
- name: Set up Docker Buildx
8639
uses: docker/setup-buildx-action@v3
8740

88-
- name: Build and push
41+
- name: Build and push Docker image
8942
uses: docker/build-push-action@v6
9043
with:
9144
context: .
9245
file: ./Dockerfile
9346
push: true
94-
tags: ${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.${{ env.AWS_REGION }}.amazonaws.com/${{ env.ECR_REPO }}:${{github.sha}}
47+
tags: ${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.${{ env.AWS_REGION }}.amazonaws.com/${{ env.ECR_REPO }}:${{ github.sha }}
9548
cache-from: type=registry,ref=${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.${{ env.AWS_REGION }}.amazonaws.com/${{ env.ECR_REPO }}:buildcache
9649
cache-to: type=registry,ref=${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.${{ env.AWS_REGION }}.amazonaws.com/${{ env.ECR_REPO }}:buildcache,mode=max
9750
provenance: false
9851

99-
- name: Get latest task definition
52+
- name: Get current task definition
10053
run: |
10154
aws ecs describe-task-definition \
10255
--task-definition tcf-prod-task \
10356
--query taskDefinition > task-definition.json
10457
105-
- name: Add image in ECS task definition
58+
- name: Update task definition with new image
10659
id: task-def
10760
uses: aws-actions/amazon-ecs-render-task-definition@v1
10861
with:
10962
task-definition: task-definition.json
11063
container-name: ${{ env.ECR_CONTAINER_NAME }}
111-
image: ${{ env.AWS_ACCOUNT_ID }}.dkr.ecr.${{ env.AWS_REGION }}.amazonaws.com/${{ env.ECR_REPO }}:${{github.sha}}
64+
image: ${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.${{ env.AWS_REGION }}.amazonaws.com/${{ env.ECR_REPO }}:${{ github.sha }}
11265

113-
- name: Deploy Amazon ECS task definition
66+
- name: Deploy to Amazon ECS
11467
uses: aws-actions/amazon-ecs-deploy-task-definition@v2
11568
with:
11669
task-definition: ${{ steps.task-def.outputs.task-definition }}

.github/workflows/ci.yml

Lines changed: 15 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -5,40 +5,19 @@ on:
55
pull_request:
66
branches:
77
- "*"
8-
# The following is needed to run tests upon direct push to dev or master
98
push:
109
branches: [dev, master]
10+
1111
env:
1212
PYTHON_TARGET: 3.11
13-
# Django
1413
DJANGO_SETTINGS_MODULE: tcf_core.settings.ci
15-
SECRET_KEY: ${{ secrets.SECRET_KEY }}
16-
DEBUG: 1
17-
ENVIRONMENT: dev
18-
# database
19-
DB_NAME: tcf_db # arbitrary string
20-
DB_USER: postgres # default user
21-
DB_PASSWORD: postgres # default password
22-
DB_HOST: localhost # required for GitHub Actions
23-
DB_PORT: 5432 # default port
24-
# AWS Cognito
25-
COGNITO_USER_POOL_ID: ${{ secrets.COGNITO_USER_POOL_ID }}
26-
COGNITO_APP_CLIENT_ID: ${{ secrets.COGNITO_APP_CLIENT_ID }}
27-
COGNITO_APP_CLIENT_SECRET: ${{ secrets.COGNITO_APP_CLIENT_SECRET }}
28-
COGNITO_DOMAIN: ${{ secrets.COGNITO_DOMAIN }}
29-
COGNITO_REGION_NAME: ${{ secrets.COGNITO_REGION_NAME }}
30-
# email for account verification
31-
EMAIL_HOST_USER: ${{ secrets.EMAIL_HOST_USER }}
32-
EMAIL_HOST_PASSWORD: ${{ secrets.EMAIL_HOST_PASSWORD }}
33-
# review drive account information
34-
REVIEW_DRIVE_ID: ${{ secrets.REVIEW_DRIVE_ID }}
35-
REVIEW_DRIVE_EMAIL: ${{ secrets.REVIEW_DRIVE_EMAIL }}
36-
REVIEW_DRIVE_PASSWORD: ${{ secrets.REVIEW_DRIVE_PASSWORD }}
37-
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
38-
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
39-
AWS_ACCOUNT_ID: ${{ secrets.AWS_ACCOUNT_ID }}
40-
AWS_STORAGE_BUCKET_NAME: ${{ secrets.AWS_STORAGE_BUCKET_NAME }}
41-
AWS_S3_CUSTOM_DOMAIN: ${{ secrets.AWS_S3_CUSTOM_DOMAIN }}
14+
SECRET_KEY: ci-secret-key-not-for-production
15+
# CI database (GitHub Actions postgres service)
16+
DB_NAME: tcf_db
17+
DB_USER: postgres
18+
DB_PASSWORD: postgres
19+
DB_HOST: localhost
20+
DB_PORT: 5432
4221

4322
jobs:
4423
pylint:
@@ -51,12 +30,12 @@ jobs:
5130
with:
5231
python-version: ${{ env.PYTHON_TARGET }}
5332
cache: 'pip'
33+
cache-dependency-path: 'requirements/*.txt'
5434

55-
- name: Install Python packages, excluding the unnecessary ones
35+
- name: Install dependencies
5636
run: |
5737
python -m pip install --upgrade pip
58-
sed -i '/\(coverage\|types\-tqdm\|black\|isort\|gunicorn\|django\-heroku\|uwsgi\)/d' requirements.txt
59-
pip install -r requirements.txt
38+
pip install -r requirements/ci.txt
6039
6140
- name: Run pylint
6241
run: |
@@ -71,12 +50,11 @@ jobs:
7150
postgres:
7251
image: postgres:15.4
7352
env:
74-
POSTGRES_USER: ${{ env.DB_USER}}
53+
POSTGRES_USER: ${{ env.DB_USER }}
7554
POSTGRES_PASSWORD: ${{ env.DB_PASSWORD }}
7655
POSTGRES_DB: ${{ env.DB_NAME }}
7756
ports:
7857
- 5432:5432
79-
# needed because the postgres container does not provide a healthcheck
8058
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
8159
steps:
8260
- uses: actions/checkout@v4
@@ -86,16 +64,15 @@ jobs:
8664
with:
8765
python-version: ${{ env.PYTHON_TARGET }}
8866
cache: 'pip'
67+
cache-dependency-path: 'requirements/*.txt'
8968

90-
- name: Install Python packages, excluding the unnecessary ones
69+
- name: Install dependencies
9170
run: |
9271
python -m pip install --upgrade pip
93-
sed -i '/\(lint\|mypy\|types\-tqdm\|black\|isort\|gunicorn\|django\-stubs\|uwsgi\)/d' requirements.txt
94-
pip install -r requirements.txt
72+
pip install -r requirements/ci.txt
9573
9674
- name: Migrations & Tests
9775
run: |
98-
envsubst < .env.example > .env
9976
python manage.py migrate
10077
coverage run manage.py test
10178

Dockerfile

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@ RUN apt-get update && \
1414

1515
WORKDIR /app
1616

17-
COPY requirements.txt /app
18-
19-
RUN pip3 install -r requirements.txt --disable-pip-version-check --no-cache-dir
17+
# Copy requirements and install (use dev.txt for local, base.txt for prod)
18+
ARG REQUIREMENTS=requirements/base.txt
19+
COPY requirements/ /app/requirements/
20+
RUN pip3 install -r /app/${REQUIREMENTS} --disable-pip-version-check --no-cache-dir
2021

2122
COPY . /app/
2223

docker-compose.yml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,19 @@ version: "3"
22

33
services:
44
web:
5-
build: .
5+
build:
6+
context: .
7+
args:
8+
REQUIREMENTS: requirements/dev.txt
69
command:
7-
bash -c "if [ \"${ENVIRONMENT}\" = 'dev' ]; then /wait-for-it.sh tcf_db:${DB_PORT} || exit 1; fi && \
10+
bash -c "/wait-for-it.sh tcf_db:${DB_PORT} -- \
811
python manage.py migrate && \
912
python manage.py collectstatic --noinput && \
1013
python manage.py invalidate_cachalot tcf_website && \
1114
echo 'Starting Django Server...' && \
1215
python manage.py runserver 0.0.0.0:8000"
16+
environment:
17+
- DJANGO_SETTINGS_MODULE=tcf_core.settings.dev
1318
volumes:
1419
- .:/app
1520
- /app/db/ # exclude the subfolder to prevent potential interference
Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,17 @@
1+
# Core dependencies for all environments
12
Django~=4.2.8
23
asgiref~=3.6.0
34
backoff~=2.2.1
4-
black~=24.1.1
55
boto3~=1.37.4
6-
coverage~=7.3.3
76
django-cachalot~=2.6.1
87
django-environ~=0.11.2
98
django-filter~=23.5
109
django-storages~=1.14.5
11-
django-stubs~=4.2.7
1210
djangorestframework~=3.14.0
1311
gunicorn~=21.2.0
14-
html-linter~=0.4.0
15-
isort~=5.13.2
16-
mypy-extensions~=1.0.0
17-
mypy~=1.7.1
1812
numpy~=1.26.2
1913
pandas~=2.1.4
2014
psycopg[binary]>=3.2.12
21-
pylint-django~=2.5.5
22-
pylint~=3.0.3
15+
python-jose~=3.4.0
2316
requests~=2.31.0
2417
tqdm~=4.66.1
25-
types-tqdm~=4.66.0
26-
uWSGI~=2.0.28
27-
python-jose~=3.4.0

requirements/ci.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# CI dependencies (includes base + testing/linting tools)
2+
-r base.txt
3+
4+
# Linting (for pylint job)
5+
pylint~=3.0.3
6+
pylint-django~=2.5.5
7+
django-stubs~=4.2.7
8+
9+
# Testing (for django job)
10+
coverage~=7.3.3

0 commit comments

Comments
 (0)