diff --git a/.woodpecker.yml b/.woodpecker.yml new file mode 100644 index 0000000..8836806 --- /dev/null +++ b/.woodpecker.yml @@ -0,0 +1,33 @@ +# .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] diff --git a/.woodpecker/.build.yml b/.woodpecker/.build.yml deleted file mode 100644 index 67c27c7..0000000 --- a/.woodpecker/.build.yml +++ /dev/null @@ -1,22 +0,0 @@ -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, - ] diff --git a/.woodpecker/.deploy.yml b/.woodpecker/.deploy.yml deleted file mode 100644 index 1e9d6de..0000000 --- a/.woodpecker/.deploy.yml +++ /dev/null @@ -1,31 +0,0 @@ -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 diff --git a/Dockerfile b/Dockerfile index 70158f1..fef478e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,10 +14,18 @@ RUN chown root:root /tmp RUN chmod 1777 /tmp # Install packages -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 +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 -# (Firefox) Download the latest Geckodriver and install it +# 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 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 diff --git a/README.md b/README.md index 9cff4a1..093c61b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ## DRF-Template -![Build Status](https://woodpecker.06222001.xyz/api/badges/2/status.svg) +![Build Status](https://woodpecker.06222001.xyz/api/badges/1/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.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.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. ### URLs diff --git a/backend/schema.yml b/backend/schema.yml index 7162675..743c2ff 100644 --- a/backend/schema.yml +++ b/backend/schema.yml @@ -6,12 +6,12 @@ info: paths: /api/v1/accounts/jwt/create/: post: - operationId: accounts_jwt_create_create + operationId: api_v1_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: - - accounts + - api requestBody: content: application/json: @@ -33,12 +33,12 @@ paths: description: '' /api/v1/accounts/jwt/refresh/: post: - operationId: accounts_jwt_refresh_create + operationId: api_v1_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: - - accounts + - api requestBody: content: application/json: @@ -60,12 +60,12 @@ paths: description: '' /api/v1/accounts/jwt/verify/: post: - operationId: accounts_jwt_verify_create + operationId: api_v1_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: - - accounts + - api requestBody: content: application/json: @@ -87,9 +87,9 @@ paths: description: '' /api/v1/accounts/users/: get: - operationId: accounts_users_list + operationId: api_v1_accounts_users_list tags: - - accounts + - api security: - jwtAuth: [] responses: @@ -102,9 +102,9 @@ paths: $ref: '#/components/schemas/CustomUser' description: '' post: - operationId: accounts_users_create + operationId: api_v1_accounts_users_create tags: - - accounts + - api requestBody: content: application/json: @@ -129,7 +129,7 @@ paths: description: '' /api/v1/accounts/users/{id}/: get: - operationId: accounts_users_retrieve + operationId: api_v1_accounts_users_retrieve parameters: - in: path name: id @@ -138,7 +138,7 @@ paths: description: A unique integer value identifying this user. required: true tags: - - accounts + - api security: - jwtAuth: [] - {} @@ -150,7 +150,7 @@ paths: $ref: '#/components/schemas/CustomUser' description: '' put: - operationId: accounts_users_update + operationId: api_v1_accounts_users_update parameters: - in: path name: id @@ -159,7 +159,7 @@ paths: description: A unique integer value identifying this user. required: true tags: - - accounts + - api requestBody: content: application/json: @@ -183,7 +183,7 @@ paths: $ref: '#/components/schemas/CustomUser' description: '' patch: - operationId: accounts_users_partial_update + operationId: api_v1_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: - - accounts + - api requestBody: content: application/json: @@ -215,7 +215,7 @@ paths: $ref: '#/components/schemas/CustomUser' description: '' delete: - operationId: accounts_users_destroy + operationId: api_v1_accounts_users_destroy parameters: - in: path name: id @@ -224,7 +224,7 @@ paths: description: A unique integer value identifying this user. required: true tags: - - accounts + - api security: - jwtAuth: [] responses: @@ -232,9 +232,9 @@ paths: description: No response body /api/v1/accounts/users/activation/: post: - operationId: accounts_users_activation_create + operationId: api_v1_accounts_users_activation_create tags: - - accounts + - api requestBody: content: application/json: @@ -259,9 +259,9 @@ paths: description: '' /api/v1/accounts/users/me/: get: - operationId: accounts_users_me_retrieve + operationId: api_v1_accounts_users_me_retrieve tags: - - accounts + - api security: - jwtAuth: [] - {} @@ -273,9 +273,9 @@ paths: $ref: '#/components/schemas/CustomUser' description: '' put: - operationId: accounts_users_me_update + operationId: api_v1_accounts_users_me_update tags: - - accounts + - api requestBody: content: application/json: @@ -299,9 +299,9 @@ paths: $ref: '#/components/schemas/CustomUser' description: '' patch: - operationId: accounts_users_me_partial_update + operationId: api_v1_accounts_users_me_partial_update tags: - - accounts + - api requestBody: content: application/json: @@ -324,9 +324,9 @@ paths: $ref: '#/components/schemas/CustomUser' description: '' delete: - operationId: accounts_users_me_destroy + operationId: api_v1_accounts_users_me_destroy tags: - - accounts + - api security: - jwtAuth: [] responses: @@ -334,9 +334,9 @@ paths: description: No response body /api/v1/accounts/users/resend_activation/: post: - operationId: accounts_users_resend_activation_create + operationId: api_v1_accounts_users_resend_activation_create tags: - - accounts + - api requestBody: content: application/json: @@ -361,9 +361,9 @@ paths: description: '' /api/v1/accounts/users/reset_password/: post: - operationId: accounts_users_reset_password_create + operationId: api_v1_accounts_users_reset_password_create tags: - - accounts + - api requestBody: content: application/json: @@ -388,9 +388,9 @@ paths: description: '' /api/v1/accounts/users/reset_password_confirm/: post: - operationId: accounts_users_reset_password_confirm_create + operationId: api_v1_accounts_users_reset_password_confirm_create tags: - - accounts + - api requestBody: content: application/json: @@ -415,9 +415,9 @@ paths: description: '' /api/v1/accounts/users/reset_username/: post: - operationId: accounts_users_reset_username_create + operationId: api_v1_accounts_users_reset_username_create tags: - - accounts + - api requestBody: content: application/json: @@ -441,9 +441,9 @@ paths: description: '' /api/v1/accounts/users/reset_username_confirm/: post: - operationId: accounts_users_reset_username_confirm_create + operationId: api_v1_accounts_users_reset_username_confirm_create tags: - - accounts + - api requestBody: content: application/json: @@ -467,9 +467,9 @@ paths: description: '' /api/v1/accounts/users/set_password/: post: - operationId: accounts_users_set_password_create + operationId: api_v1_accounts_users_set_password_create tags: - - accounts + - api requestBody: content: application/json: @@ -493,9 +493,9 @@ paths: description: '' /api/v1/accounts/users/set_username/: post: - operationId: accounts_users_set_username_create + operationId: api_v1_accounts_users_set_username_create tags: - - accounts + - api requestBody: content: application/json: @@ -519,9 +519,9 @@ paths: description: '' /api/v1/billing/: get: - operationId: billing_retrieve + operationId: api_v1_billing_retrieve tags: - - billing + - api security: - jwtAuth: [] responses: @@ -529,9 +529,9 @@ paths: description: No response body /api/v1/notifications/: get: - operationId: notifications_list + operationId: api_v1_notifications_list tags: - - notifications + - api security: - jwtAuth: [] - {} @@ -546,7 +546,7 @@ paths: description: '' /api/v1/notifications/{id}/: get: - operationId: notifications_retrieve + operationId: api_v1_notifications_retrieve parameters: - in: path name: id @@ -555,7 +555,7 @@ paths: description: A unique integer value identifying this notification. required: true tags: - - notifications + - api security: - jwtAuth: [] - {} @@ -567,7 +567,7 @@ paths: $ref: '#/components/schemas/Notification' description: '' patch: - operationId: notifications_partial_update + operationId: api_v1_notifications_partial_update parameters: - in: path name: id @@ -576,7 +576,7 @@ paths: description: A unique integer value identifying this notification. required: true tags: - - notifications + - api requestBody: content: application/json: @@ -599,7 +599,7 @@ paths: $ref: '#/components/schemas/Notification' description: '' delete: - operationId: notifications_destroy + operationId: api_v1_notifications_destroy parameters: - in: path name: id @@ -608,7 +608,7 @@ paths: description: A unique integer value identifying this notification. required: true tags: - - notifications + - api security: - jwtAuth: [] - {} @@ -617,9 +617,9 @@ paths: description: No response body /api/v1/stripe/checkout_session/: post: - operationId: stripe_checkout_session_create + operationId: api_v1_stripe_checkout_session_create tags: - - stripe + - api requestBody: content: application/json: @@ -639,9 +639,9 @@ paths: description: No response body /api/v1/stripe/webhook/: post: - operationId: stripe_webhook_create + operationId: api_v1_stripe_webhook_create tags: - - stripe + - api security: - jwtAuth: [] - {} @@ -650,9 +650,9 @@ paths: description: No response body /api/v1/subscriptions/plans/: get: - operationId: subscriptions_plans_list + operationId: api_v1_subscriptions_plans_list tags: - - subscriptions + - api security: - jwtAuth: [] - {} @@ -667,7 +667,7 @@ paths: description: '' /api/v1/subscriptions/plans/{id}/: get: - operationId: subscriptions_plans_retrieve + operationId: api_v1_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: - - subscriptions + - api security: - jwtAuth: [] - {} @@ -689,9 +689,9 @@ paths: description: '' /api/v1/subscriptions/self/: get: - operationId: subscriptions_self_list + operationId: api_v1_subscriptions_self_list tags: - - subscriptions + - api security: - jwtAuth: [] responses: @@ -705,7 +705,7 @@ paths: description: '' /api/v1/subscriptions/self/{id}/: get: - operationId: subscriptions_self_retrieve + operationId: api_v1_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: - - subscriptions + - api security: - jwtAuth: [] responses: @@ -726,9 +726,9 @@ paths: description: '' /api/v1/subscriptions/user_group/: get: - operationId: subscriptions_user_group_list + operationId: api_v1_subscriptions_user_group_list tags: - - subscriptions + - api security: - jwtAuth: [] responses: @@ -742,7 +742,7 @@ paths: description: '' /api/v1/subscriptions/user_group/{id}/: get: - operationId: subscriptions_user_group_retrieve + operationId: api_v1_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: - - subscriptions + - api security: - jwtAuth: [] responses: diff --git a/backend/webdriver/tasks.py b/backend/webdriver/tasks.py index 33b390a..50c355b 100644 --- a/backend/webdriver/tasks.py +++ b/backend/webdriver/tasks.py @@ -23,8 +23,7 @@ def sample_selenium_task(): @shared_task(autoretry_for=(Exception,), retry_kwargs={'max_retries': 3, 'countdown': 5}) def simple_google_search(): - driver = setup_webdriver(driver_type="firefox", - use_proxy=False, use_saved_session=False) + driver = setup_webdriver(use_proxy=False, use_saved_session=False) driver.get(f"https://google.com/") google_search(driver, search_term="cat blog posts") diff --git a/docker-compose.yml b/docker-compose.demo.yml similarity index 84% rename from docker-compose.yml rename to docker-compose.demo.yml index e935f1c..803b6f2 100644 --- a/docker-compose.yml +++ b/docker-compose.demo.yml @@ -1,8 +1,10 @@ +version: "3.9" + services: # Django Backend django: env_file: .env - image: git.06222001.xyz/keannu125/drf_template:latest + image: keannu125/drf-template:latest ports: - "${BACKEND_PORT}:8000" environment: @@ -10,18 +12,16 @@ services: - RUN_TYPE=web depends_on: - postgres - - pgbouncer # Django Celery Worker celery: env_file: .env environment: - RUN_TYPE=worker - image: git.06222001.xyz/keannu125/drf_template:latest + image: keannu125/drf-template:latest depends_on: - django - postgres - - pgbouncer - redis # Run multiple worker instances scale: 4 @@ -31,12 +31,11 @@ services: env_file: .env environment: - RUN_TYPE=beat - image: git.06222001.xyz/keannu125/drf_template:latest + image: keannu125/drf-template:latest depends_on: - celery - django - postgres - - pgbouncer - redis # SQL Database @@ -48,7 +47,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 @@ -77,4 +76,4 @@ services: command: listen --forward-to django:8000/api/v1/stripe/webhook/ volumes: - db_data: + db-data: diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index 03ea04d..37f8422 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -1,3 +1,5 @@ +version: "3.9" + services: # Django Backend django: