Skip to content

Commit 34c70c2

Browse files
authored
Merge pull request #16 from akirachix/feature/deployment
Feature/deployment
2 parents e7bcb80 + 1bcf5f1 commit 34c70c2

File tree

7 files changed

+97
-48
lines changed

7 files changed

+97
-48
lines changed

.github/workflows/ci-deploy.yml

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
name: Django Deployment CI
2+
3+
on:
4+
push:
5+
branches: [ "main" ]
6+
7+
jobs:
8+
release:
9+
runs-on: ubuntu-latest
10+
steps:
11+
- name: Checkout code
12+
uses: actions/checkout@v3
13+
14+
- name: Set up Python environment
15+
uses: actions/setup-python@v4
16+
with:
17+
python-version: 3.8.10
18+
19+
- name: Install dependencies
20+
run: |
21+
pip install -r requirements.txt
22+
23+
- name: Set up Git remote for Heroku
24+
run: |
25+
git remote -v
26+
git remote add heroku https://git.heroku.com/zenoai.git || echo "Heroku remote already exists"
27+
28+
- name: Set Heroku buildpack
29+
run: |
30+
heroku buildpacks:set heroku/python -a zenoai
31+
env:
32+
HEROKU_API_KEY: ${{ secrets.HEROKU_API_KEY }}
33+
34+
- name: Deploy to Heroku
35+
uses: akhileshns/heroku-deploy@v3.13.15
36+
with:
37+
heroku_api_key: ${{ secrets.HEROKU_API_KEY }}
38+
heroku_app_name: "zenoai"
39+
heroku_email: ${{ secrets.HEROKU_EMAIL }}

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,6 @@ db.sqlite3
88
.vscode/
99
.idea/
1010
.history/
11-
.lh/
11+
.lh/
12+
staticfiles/
13+
media/

Procfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
web: gunicorn zeno.wsgi --log-file -

requirements.txt

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,29 @@
11
asgiref==3.8.1
22
black==24.8.0
3+
certifi==2025.8.3
4+
charset-normalizer==3.4.3
35
click==8.1.8
46
django==4.2.24
7+
django-cors-headers==4.4.0
58
djangorestframework==3.15.2
9+
dotenv==0.9.9
610
drf-yasg==1.21.10
11+
gunicorn==23.0.0
12+
idna==3.10
713
inflection==0.5.1
814
mypy-extensions==1.1.0
915
packaging==25.0
1016
pathspec==0.12.1
11-
pillow==10.2.0
17+
pillow==10.4.0
1218
platformdirs==3.4.0
13-
psycopg==3.2.9
19+
psycopg==3.2.10
1420
psycopg2-binary==2.9.10
21+
python-dotenv==1.0.1
1522
pytz==2025.2
1623
pyyaml==6.0.2
24+
requests==2.32.4
1725
sqlparse==0.5.3
1826
typing-extensions==4.13.2
1927
uritemplate==4.1.1
28+
urllib3==2.2.3
2029
whitenoise==6.7.0

runtime.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
python-3.8.10

zeno/settings.py

Lines changed: 39 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
12
"""
23
Django settings for zeno project.
34
@@ -9,26 +10,21 @@
910
For the full list of settings and their values, see
1011
https://docs.djangoproject.com/en/5.2/ref/settings/
1112
"""
12-
13+
import os
1314
from pathlib import Path
15+
from dotenv import load_dotenv
1416

15-
# Build paths inside the project like this: BASE_DIR / 'subdir'.
16-
BASE_DIR = Path(__file__).resolve().parent.parent
17-
18-
19-
# Quick-start development settings - unsuitable for production
20-
# See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/
21-
22-
# SECURITY WARNING: keep the secret key used in production secret!
23-
SECRET_KEY = 'django-insecure-b3kb=syb8@z0tt)hu1is3g%ndv0c1pxwc!iy-*twyis9c&m7yl'
17+
load_dotenv()
2418

25-
# SECURITY WARNING: don't run with debug turned on in production!
26-
DEBUG = True
27-
28-
ALLOWED_HOSTS = []
19+
BASE_DIR = Path(__file__).resolve().parent.parent
2920

21+
def env_set(*names):
22+
return all(os.environ.get(name, "").strip() != "" for name in names)
3023

31-
# Application definition
24+
DJANGO_SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY')
25+
SECRET_KEY = DJANGO_SECRET_KEY
26+
DEBUG = False
27+
ALLOWED_HOSTS = ["*"]
3228

3329
INSTALLED_APPS = [
3430
'django.contrib.admin',
@@ -45,15 +41,16 @@
4541
'conversations',
4642
'runs',
4743
'drf_yasg',
48-
44+
'corsheaders',
4945
]
5046

51-
5247
MIDDLEWARE = [
48+
'corsheaders.middleware.CorsMiddleware',
5349
'django.middleware.security.SecurityMiddleware',
5450
'django.contrib.sessions.middleware.SessionMiddleware',
5551
'django.middleware.common.CommonMiddleware',
5652
'django.middleware.csrf.CsrfViewMiddleware',
53+
'whitenoise.middleware.WhiteNoiseMiddleware',
5754
'django.contrib.auth.middleware.AuthenticationMiddleware',
5855
'django.contrib.messages.middleware.MessageMiddleware',
5956
'django.middleware.clickjacking.XFrameOptionsMiddleware',
@@ -79,19 +76,24 @@
7976
WSGI_APPLICATION = 'zeno.wsgi.application'
8077

8178

82-
# Database
83-
# https://docs.djangoproject.com/en/5.2/ref/settings/#databases
84-
85-
DATABASES = {
86-
'default': {
87-
'ENGINE': 'django.db.backends.sqlite3',
88-
'NAME': BASE_DIR / 'db.sqlite3',
79+
if env_set('PGDATABASE', 'PGUSER', 'PGPASSWORD', 'PGHOST'):
80+
DATABASES = {
81+
'default': {
82+
'ENGINE': 'django.db.backends.postgresql',
83+
'NAME': os.environ['PGDATABASE'],
84+
'USER': os.environ['PGUSER'],
85+
'PASSWORD': os.environ['PGPASSWORD'],
86+
'HOST': os.environ['PGHOST'],
87+
'PORT': os.environ.get('PGPORT', '5432'),
88+
}
89+
}
90+
else:
91+
DATABASES = {
92+
'default': {
93+
'ENGINE': 'django.db.backends.sqlite3',
94+
'NAME': BASE_DIR / 'db.sqlite3',
95+
}
8996
}
90-
}
91-
92-
93-
# Password validation
94-
# https://docs.djangoproject.com/en/5.2/ref/settings/#auth-password-validators
9597

9698
AUTH_PASSWORD_VALIDATORS = [
9799
{
@@ -108,30 +110,22 @@
108110
},
109111
]
110112

111-
112-
# Internationalization
113-
# https://docs.djangoproject.com/en/5.2/topics/i18n/
114-
115113
LANGUAGE_CODE = 'en-us'
116-
117114
TIME_ZONE = 'UTC'
118-
119115
USE_I18N = True
120-
121116
USE_TZ = True
122117

118+
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
119+
STATIC_URL = '/static/'
123120

124-
# Static files (CSS, JavaScript, Images)
125-
# https://docs.djangoproject.com/en/5.2/howto/static-files/
126-
127-
STATIC_URL = 'static/'
128-
129-
# Default primary key field type
130-
# https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field
121+
STATICFILES_DIRS = (
122+
os.path.join(BASE_DIR, 'static'),
123+
)
131124

125+
MEDIA_URL = "/media/"
126+
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
132127
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
133128

134-
135129
AUTH_USER_MODEL = "users.User"
136130

137131
REST_FRAMEWORK = {
@@ -142,4 +136,5 @@
142136
'rest_framework.permissions.IsAuthenticated',
143137
],
144138
}
139+
CORS_ORIGIN_ALLOW_ALL = True
145140

zeno/urls.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
from rest_framework import permissions
44
from drf_yasg.views import get_schema_view
55
from drf_yasg import openapi
6+
from django.conf import settings
7+
from django.conf.urls.static import static
68

79
schema_view = get_schema_view(
810
openapi.Info(
@@ -23,4 +25,4 @@
2325
re_path(r'^swagger(?P<format>\.json|\.yaml)$', schema_view.without_ui(cache_timeout=0), name='schema-json'),
2426
path('swagger/', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),
2527
path('redoc/', schema_view.with_ui('redoc', cache_timeout=0), name='schema-redoc'),
26-
]
28+
]+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

0 commit comments

Comments
 (0)