Compare commits

...

13 commits

9 changed files with 136 additions and 124 deletions

View file

@ -1,33 +0,0 @@
# .woodpecker.yml
steps:
- name: build
image: docker
when:
- branch: master
event: push
commands:
- docker build --platform linux/arm64 --no-cache -t "$IMAGE" .
- echo "$REGISTRY_PASSWORD" | docker login "$REGISTRY" --password-stdin -u "$REGISTRY_USERNAME"
- docker push "$IMAGE"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
secrets: [REGISTRY, REGISTRY_USERNAME, REGISTRY_PASSWORD, IMAGE]
- name: deploy
image: docker
when:
- branch: master
event: push
commands:
- mkdir -p /root/.ssh/
- echo "$SSH_KEY" | tr -d '\r' > /root/.ssh/id_rsa
- chmod 600 /root/.ssh/id_rsa
- echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > /root/.ssh/config
- ssh "$REMOTE_HOST" "
cd $PROJECT_DIRECTORY;
docker-compose -f docker-compose.demo.yml down;
docker image rm "$IMAGE" || true;
docker volume rm "$VOLUME" || true;
docker pull "$IMAGE";
docker compose -f docker-compose.demo.yml up -d;
docker image prune -af;"
secrets: [SSH_KEY, REMOTE_HOST, PROJECT_DIRECTORY, IMAGE, VOLUME]

22
.woodpecker/.build.yml Normal file
View file

@ -0,0 +1,22 @@
labels:
platform: linux/amd64
steps:
- name: build
image: docker
when:
- branch: master
event: push
commands:
- docker build -t "$REGISTRY_IMAGE_TAG" .
- echo "$FORGEJO_REGISTRY_PASSWORD" | docker login "$FORGEJO_REGISTRY_URL" --password-stdin -u "$FORGEJO_REGISTRY_USERNAME"
- docker push "$REGISTRY_IMAGE_TAG"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
secrets:
[
FORGEJO_REGISTRY_URL,
FORGEJO_REGISTRY_USERNAME,
FORGEJO_REGISTRY_PASSWORD,
REGISTRY_IMAGE_TAG,
]

31
.woodpecker/.deploy.yml Normal file
View file

@ -0,0 +1,31 @@
steps:
- name: deploy
image: alpine:3.20
when:
- branch: master
event: push
commands:
- apk add openssh
- mkdir -p /root/.ssh/
- echo "$WOODPECKER_SSH_KEY" | tr -d '\r' > /root/.ssh/id_rsa
- chmod 600 /root/.ssh/id_rsa
- echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > /root/.ssh/config
- ssh "$SSH_HOST" '
cd "$PROJECT_DIRECTORY";
docker-compose down;
docker image rm "$REGISTRY_IMAGE_TAG" || true;
docker volume rm "$DOCKER_DB_VOLUME" || true;
docker pull "$REGISTRY_IMAGE_TAG";
docker-compose up -d;
docker image prune -af;'
secrets:
[
SSH_HOST,
PROJECT_DIRECTORY,
WOODPECKER_SSH_KEY,
REGISTRY_IMAGE_TAG,
DOCKER_DB_VOLUME,
]
depends_on:
- build

View file

@ -14,18 +14,10 @@ RUN chown root:root /tmp
RUN chmod 1777 /tmp
# Install packages
RUN apt clean
RUN apt update
RUN apt install -y graphviz libgraphviz-dev graphviz-dev wget zip
RUN pip3 install --upgrade pip
RUN pip3 install --no-cache-dir -r requirements.txt
RUN apt update && apt install -y graphviz libgraphviz-dev graphviz-dev wget zip chromium chromium-driver firefox-esr
RUN pip3 install --upgrade pip && pip3 install --no-cache-dir -r requirements.txt
# Install Chrome & Chromedriver
RUN apt install -y chromium chromium-driver
# Install Firefox and Geckodriver
RUN apt install -y firefox-esr
# Download the latest Geckodriver and install it
# (Firefox) Download the latest Geckodriver and install it
ENV GECKODRIVER_VERSION=latest
RUN wget -O geckodriver.tar.gz https://github.com/mozilla/geckodriver/releases/download/v0.35.0/geckodriver-v0.35.0-linux64.tar.gz
RUN tar -zxf geckodriver.tar.gz -C /usr/bin

View file

@ -1,6 +1,6 @@
## DRF-Template
![Build Status](https://woodpecker.06222001.xyz/api/badges/1/status.svg)
![Build Status](https://woodpecker.06222001.xyz/api/badges/2/status.svg)
![Demo Page Status](https://stats.06222001.xyz/api/badge/119/status)
This is a Django template that I personally use for my projects. This covers the following
@ -27,7 +27,7 @@ When using `docker-compose.dev.yml`, the entire project directory is mounted ont
### Deployment
A sample `docker-compose.demo.yml` is provided which I use in hosting the demo. DEBUG should be set to False when deploying as to not expose the URLs fro Celery Flower and the Django Silk Profiler. The local Inbucket container is not present so make sure to specify an external SMTP server to process emails properly.
A sample `docker-compose.yml` is provided which I use in hosting the demo. DEBUG should be set to False when deploying as to not expose the URLs fro Celery Flower and the Django Silk Profiler. The local Inbucket container is not present so make sure to specify an external SMTP server to process emails properly.
### URLs

View file

@ -6,12 +6,12 @@ info:
paths:
/api/v1/accounts/jwt/create/:
post:
operationId: api_v1_accounts_jwt_create_create
operationId: accounts_jwt_create_create
description: |-
Takes a set of user credentials and returns an access and refresh JSON web
token pair to prove the authentication of those credentials.
tags:
- api
- accounts
requestBody:
content:
application/json:
@ -33,12 +33,12 @@ paths:
description: ''
/api/v1/accounts/jwt/refresh/:
post:
operationId: api_v1_accounts_jwt_refresh_create
operationId: accounts_jwt_refresh_create
description: |-
Takes a refresh type JSON web token and returns an access type JSON web
token if the refresh token is valid.
tags:
- api
- accounts
requestBody:
content:
application/json:
@ -60,12 +60,12 @@ paths:
description: ''
/api/v1/accounts/jwt/verify/:
post:
operationId: api_v1_accounts_jwt_verify_create
operationId: accounts_jwt_verify_create
description: |-
Takes a token and indicates if it is valid. This view provides no
information about a token's fitness for a particular use.
tags:
- api
- accounts
requestBody:
content:
application/json:
@ -87,9 +87,9 @@ paths:
description: ''
/api/v1/accounts/users/:
get:
operationId: api_v1_accounts_users_list
operationId: accounts_users_list
tags:
- api
- accounts
security:
- jwtAuth: []
responses:
@ -102,9 +102,9 @@ paths:
$ref: '#/components/schemas/CustomUser'
description: ''
post:
operationId: api_v1_accounts_users_create
operationId: accounts_users_create
tags:
- api
- accounts
requestBody:
content:
application/json:
@ -129,7 +129,7 @@ paths:
description: ''
/api/v1/accounts/users/{id}/:
get:
operationId: api_v1_accounts_users_retrieve
operationId: accounts_users_retrieve
parameters:
- in: path
name: id
@ -138,7 +138,7 @@ paths:
description: A unique integer value identifying this user.
required: true
tags:
- api
- accounts
security:
- jwtAuth: []
- {}
@ -150,7 +150,7 @@ paths:
$ref: '#/components/schemas/CustomUser'
description: ''
put:
operationId: api_v1_accounts_users_update
operationId: accounts_users_update
parameters:
- in: path
name: id
@ -159,7 +159,7 @@ paths:
description: A unique integer value identifying this user.
required: true
tags:
- api
- accounts
requestBody:
content:
application/json:
@ -183,7 +183,7 @@ paths:
$ref: '#/components/schemas/CustomUser'
description: ''
patch:
operationId: api_v1_accounts_users_partial_update
operationId: accounts_users_partial_update
parameters:
- in: path
name: id
@ -192,7 +192,7 @@ paths:
description: A unique integer value identifying this user.
required: true
tags:
- api
- accounts
requestBody:
content:
application/json:
@ -215,7 +215,7 @@ paths:
$ref: '#/components/schemas/CustomUser'
description: ''
delete:
operationId: api_v1_accounts_users_destroy
operationId: accounts_users_destroy
parameters:
- in: path
name: id
@ -224,7 +224,7 @@ paths:
description: A unique integer value identifying this user.
required: true
tags:
- api
- accounts
security:
- jwtAuth: []
responses:
@ -232,9 +232,9 @@ paths:
description: No response body
/api/v1/accounts/users/activation/:
post:
operationId: api_v1_accounts_users_activation_create
operationId: accounts_users_activation_create
tags:
- api
- accounts
requestBody:
content:
application/json:
@ -259,9 +259,9 @@ paths:
description: ''
/api/v1/accounts/users/me/:
get:
operationId: api_v1_accounts_users_me_retrieve
operationId: accounts_users_me_retrieve
tags:
- api
- accounts
security:
- jwtAuth: []
- {}
@ -273,9 +273,9 @@ paths:
$ref: '#/components/schemas/CustomUser'
description: ''
put:
operationId: api_v1_accounts_users_me_update
operationId: accounts_users_me_update
tags:
- api
- accounts
requestBody:
content:
application/json:
@ -299,9 +299,9 @@ paths:
$ref: '#/components/schemas/CustomUser'
description: ''
patch:
operationId: api_v1_accounts_users_me_partial_update
operationId: accounts_users_me_partial_update
tags:
- api
- accounts
requestBody:
content:
application/json:
@ -324,9 +324,9 @@ paths:
$ref: '#/components/schemas/CustomUser'
description: ''
delete:
operationId: api_v1_accounts_users_me_destroy
operationId: accounts_users_me_destroy
tags:
- api
- accounts
security:
- jwtAuth: []
responses:
@ -334,9 +334,9 @@ paths:
description: No response body
/api/v1/accounts/users/resend_activation/:
post:
operationId: api_v1_accounts_users_resend_activation_create
operationId: accounts_users_resend_activation_create
tags:
- api
- accounts
requestBody:
content:
application/json:
@ -361,9 +361,9 @@ paths:
description: ''
/api/v1/accounts/users/reset_password/:
post:
operationId: api_v1_accounts_users_reset_password_create
operationId: accounts_users_reset_password_create
tags:
- api
- accounts
requestBody:
content:
application/json:
@ -388,9 +388,9 @@ paths:
description: ''
/api/v1/accounts/users/reset_password_confirm/:
post:
operationId: api_v1_accounts_users_reset_password_confirm_create
operationId: accounts_users_reset_password_confirm_create
tags:
- api
- accounts
requestBody:
content:
application/json:
@ -415,9 +415,9 @@ paths:
description: ''
/api/v1/accounts/users/reset_username/:
post:
operationId: api_v1_accounts_users_reset_username_create
operationId: accounts_users_reset_username_create
tags:
- api
- accounts
requestBody:
content:
application/json:
@ -441,9 +441,9 @@ paths:
description: ''
/api/v1/accounts/users/reset_username_confirm/:
post:
operationId: api_v1_accounts_users_reset_username_confirm_create
operationId: accounts_users_reset_username_confirm_create
tags:
- api
- accounts
requestBody:
content:
application/json:
@ -467,9 +467,9 @@ paths:
description: ''
/api/v1/accounts/users/set_password/:
post:
operationId: api_v1_accounts_users_set_password_create
operationId: accounts_users_set_password_create
tags:
- api
- accounts
requestBody:
content:
application/json:
@ -493,9 +493,9 @@ paths:
description: ''
/api/v1/accounts/users/set_username/:
post:
operationId: api_v1_accounts_users_set_username_create
operationId: accounts_users_set_username_create
tags:
- api
- accounts
requestBody:
content:
application/json:
@ -519,9 +519,9 @@ paths:
description: ''
/api/v1/billing/:
get:
operationId: api_v1_billing_retrieve
operationId: billing_retrieve
tags:
- api
- billing
security:
- jwtAuth: []
responses:
@ -529,9 +529,9 @@ paths:
description: No response body
/api/v1/notifications/:
get:
operationId: api_v1_notifications_list
operationId: notifications_list
tags:
- api
- notifications
security:
- jwtAuth: []
- {}
@ -546,7 +546,7 @@ paths:
description: ''
/api/v1/notifications/{id}/:
get:
operationId: api_v1_notifications_retrieve
operationId: notifications_retrieve
parameters:
- in: path
name: id
@ -555,7 +555,7 @@ paths:
description: A unique integer value identifying this notification.
required: true
tags:
- api
- notifications
security:
- jwtAuth: []
- {}
@ -567,7 +567,7 @@ paths:
$ref: '#/components/schemas/Notification'
description: ''
patch:
operationId: api_v1_notifications_partial_update
operationId: notifications_partial_update
parameters:
- in: path
name: id
@ -576,7 +576,7 @@ paths:
description: A unique integer value identifying this notification.
required: true
tags:
- api
- notifications
requestBody:
content:
application/json:
@ -599,7 +599,7 @@ paths:
$ref: '#/components/schemas/Notification'
description: ''
delete:
operationId: api_v1_notifications_destroy
operationId: notifications_destroy
parameters:
- in: path
name: id
@ -608,7 +608,7 @@ paths:
description: A unique integer value identifying this notification.
required: true
tags:
- api
- notifications
security:
- jwtAuth: []
- {}
@ -617,9 +617,9 @@ paths:
description: No response body
/api/v1/stripe/checkout_session/:
post:
operationId: api_v1_stripe_checkout_session_create
operationId: stripe_checkout_session_create
tags:
- api
- stripe
requestBody:
content:
application/json:
@ -639,9 +639,9 @@ paths:
description: No response body
/api/v1/stripe/webhook/:
post:
operationId: api_v1_stripe_webhook_create
operationId: stripe_webhook_create
tags:
- api
- stripe
security:
- jwtAuth: []
- {}
@ -650,9 +650,9 @@ paths:
description: No response body
/api/v1/subscriptions/plans/:
get:
operationId: api_v1_subscriptions_plans_list
operationId: subscriptions_plans_list
tags:
- api
- subscriptions
security:
- jwtAuth: []
- {}
@ -667,7 +667,7 @@ paths:
description: ''
/api/v1/subscriptions/plans/{id}/:
get:
operationId: api_v1_subscriptions_plans_retrieve
operationId: subscriptions_plans_retrieve
parameters:
- in: path
name: id
@ -676,7 +676,7 @@ paths:
description: A unique integer value identifying this subscription plan.
required: true
tags:
- api
- subscriptions
security:
- jwtAuth: []
- {}
@ -689,9 +689,9 @@ paths:
description: ''
/api/v1/subscriptions/self/:
get:
operationId: api_v1_subscriptions_self_list
operationId: subscriptions_self_list
tags:
- api
- subscriptions
security:
- jwtAuth: []
responses:
@ -705,7 +705,7 @@ paths:
description: ''
/api/v1/subscriptions/self/{id}/:
get:
operationId: api_v1_subscriptions_self_retrieve
operationId: subscriptions_self_retrieve
parameters:
- in: path
name: id
@ -714,7 +714,7 @@ paths:
description: A unique integer value identifying this user subscription.
required: true
tags:
- api
- subscriptions
security:
- jwtAuth: []
responses:
@ -726,9 +726,9 @@ paths:
description: ''
/api/v1/subscriptions/user_group/:
get:
operationId: api_v1_subscriptions_user_group_list
operationId: subscriptions_user_group_list
tags:
- api
- subscriptions
security:
- jwtAuth: []
responses:
@ -742,7 +742,7 @@ paths:
description: ''
/api/v1/subscriptions/user_group/{id}/:
get:
operationId: api_v1_subscriptions_user_group_retrieve
operationId: subscriptions_user_group_retrieve
parameters:
- in: path
name: id
@ -751,7 +751,7 @@ paths:
description: A unique integer value identifying this user subscription.
required: true
tags:
- api
- subscriptions
security:
- jwtAuth: []
responses:

View file

@ -23,7 +23,8 @@ def sample_selenium_task():
@shared_task(autoretry_for=(Exception,), retry_kwargs={'max_retries': 3, 'countdown': 5})
def simple_google_search():
driver = setup_webdriver(use_proxy=False, use_saved_session=False)
driver = setup_webdriver(driver_type="firefox",
use_proxy=False, use_saved_session=False)
driver.get(f"https://google.com/")
google_search(driver, search_term="cat blog posts")

View file

@ -1,5 +1,3 @@
version: "3.9"
services:
# Django Backend
django:

View file

@ -1,10 +1,8 @@
version: "3.9"
services:
# Django Backend
django:
env_file: .env
image: keannu125/drf-template:latest
image: git.06222001.xyz/keannu125/drf_template:latest
ports:
- "${BACKEND_PORT}:8000"
environment:
@ -12,16 +10,18 @@ services:
- RUN_TYPE=web
depends_on:
- postgres
- pgbouncer
# Django Celery Worker
celery:
env_file: .env
environment:
- RUN_TYPE=worker
image: keannu125/drf-template:latest
image: git.06222001.xyz/keannu125/drf_template:latest
depends_on:
- django
- postgres
- pgbouncer
- redis
# Run multiple worker instances
scale: 4
@ -31,11 +31,12 @@ services:
env_file: .env
environment:
- RUN_TYPE=beat
image: keannu125/drf-template:latest
image: git.06222001.xyz/keannu125/drf_template:latest
depends_on:
- celery
- django
- postgres
- pgbouncer
- redis
# SQL Database
@ -47,7 +48,7 @@ services:
- POSTGRES_USER=${DB_USERNAME}
- POSTGRES_PASSWORD=${DB_PASSWORD}
volumes:
- db-data:/var/lib/postgresql/data
- db_data:/var/lib/postgresql/data
command: postgres -c max_connections=200
# DB Bouncer
@ -76,4 +77,4 @@ services:
command: listen --forward-to django:8000/api/v1/stripe/webhook/
volumes:
db-data:
db_data: