diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 33062287..5d6bcb53 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,18 +1,20 @@ -# Краткое название +# Что изменено -## Описание изменений +Кратко опишите изменения и при необходимости приложите ссылку на задачу. -_Опишите изменения, которые вы внесли в код. Не забывайте указывать номер задачи или ссылку на тикет._ +## Проверка +Укажите, как проверялись изменения. -## Тестирование +- автоматические проверки +- ручная проверка +- шаги для воспроизведения +- ожидаемый результат -_Опишите, как тестировали свои изменения. Например, какие тесты проходят, а какие нет._ +## Риски и ограничения -## Проверка кода +Укажите важные ограничения и возможные побочные эффекты. -_Опишите, как проверить ваш код._ - -## Дополнительная информация - -_Здесь вы можете добавить какую-либо дополнительную информацию о своих изменениях._ +- миграции, изменения переменных окружения, feature flags +- замечания по деплою +- места, которые требуют повышенного внимания diff --git a/.github/workflows/django-test.yml b/.github/workflows/ci.yml similarity index 67% rename from .github/workflows/django-test.yml rename to .github/workflows/ci.yml index 26a56bd9..fa92e86d 100644 --- a/.github/workflows/django-test.yml +++ b/.github/workflows/ci.yml @@ -1,12 +1,32 @@ -name: Django CI +name: CI on: push: branches: - - '**' + - "**" jobs: - django-test: + lint: + name: Lint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Set up Python 3.11 + uses: actions/setup-python@v4 + with: + python-version: 3.11 + + - name: Install lint dependencies + run: | + python -m pip install --upgrade pip + pip install flake8 + + - name: Run flake8 + run: flake8 $(git ls-files '*.py') + + test: + name: Tests runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 @@ -45,4 +65,4 @@ jobs: env: DEBUG: True DJANGO_SETTINGS_MODULE: procollab.settings - PYTHONUNBUFFERED: 1 \ No newline at end of file + PYTHONUNBUFFERED: 1 diff --git a/.github/workflows/dev-ci.yml b/.github/workflows/dev-ci.yml index 1600f184..dcfd87b1 100644 --- a/.github/workflows/dev-ci.yml +++ b/.github/workflows/dev-ci.yml @@ -1,4 +1,4 @@ -name: 'Deploy dev server' +name: Deploy Dev on: push: @@ -8,9 +8,10 @@ on: jobs: deploy: + name: Deploy runs-on: ubuntu-latest steps: - - name: run on server + - name: Deploy to server uses: garygrossgarten/github-action-ssh@release with: host: ${{ secrets.DEV_SERVER_HOST }} @@ -32,20 +33,20 @@ jobs: echo "DATABASE_HOST=${{ secrets.DEV_DATABASE_HOST }}" >> .env && echo "DATABASE_PORT=${{ secrets.DEV_DATABASE_PORT }}" >> .env && - echo "EMAIL_USER=${{ secrets.EMAIL_USER }}" >> .env && - echo "EMAIL_PASSWORD=${{ secrets.EMAIL_PASSWORD }}" >> .env && - echo "EMAIL_HOST=${{ secrets.EMAIL_HOST }}" >> .env && - echo "EMAIL_PORT=${{ secrets.EMAIL_PORT }}" >> .env && + echo "SELECTEL_ACCOUNT_ID=${{ secrets.SELECTEL_ACCOUNT_ID }}" >> .env && echo "SELECTEL_CONTAINER_NAME=${{ secrets.SELECTEL_CONTAINER_NAME }}" >> .env && echo "SELECTEL_CONTAINER_PASSWORD=${{ secrets.SELECTEL_CONTAINER_PASSWORD }}" >> .env && echo "SELECTEL_CONTAINER_USERNAME=${{ secrets.SELECTEL_CONTAINER_USERNAME }}" >> .env && - echo "CLICKUP_API_TOKEN=${{ secrets.CLICKUP_API_TOKEN }}" >> .env && - echo "CLICKUP_SPACE_ID=${{ secrets.CLICKUP_SPACE_ID }}" >> .env && - - echo "SENTRY_DSN=${{ secrets.SENTRY_DSN }}" >> .env && - + echo "EMAIL_USER=${{ secrets.EMAIL_USER }}" >> .env && echo "UNISENDER_GO_API_KEY=${{ secrets.UNISENDER_GO_API_KEY }}" >> .env && - docker compose -f docker-compose.dev-ci.yml up -d --build --force-recreate + docker compose -f docker-compose.dev-ci.yml up -d --build --force-recreate --remove-orphans && + + install -d /etc/nginx/procollab/includes && + install -m 644 deploy/nginx/host/includes/proxy_app.inc /etc/nginx/procollab/includes/proxy_app.inc && + install -m 644 deploy/nginx/host/dev/dev.procollab.ru /etc/nginx/sites-available/dev.procollab.ru && + ln -sfn /etc/nginx/sites-available/dev.procollab.ru /etc/nginx/sites-enabled/dev.procollab.ru && + nginx -t && + systemctl reload nginx diff --git a/.github/workflows/lints.yml b/.github/workflows/lints.yml deleted file mode 100644 index e435855b..00000000 --- a/.github/workflows/lints.yml +++ /dev/null @@ -1,29 +0,0 @@ -name: Pylint - -on: - push: - branches: - - '*' # matches every branch that doesn't contain a '/' - - '*/*' # matches every branch containing a single '/' - - '**' # matches every branch - - -jobs: - build: - runs-on: ubuntu-latest - strategy: - matrix: - python-version: [3.11] - steps: - - uses: actions/checkout@v3 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v3 - with: - python-version: ${{ matrix.python-version }} - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install flake8 - - name: Analysing the code with flake8 - run: | - flake8 $(git ls-files '*.py') diff --git a/.github/workflows/new_deploy.yml b/.github/workflows/new_deploy.yml deleted file mode 100644 index 823a8c06..00000000 --- a/.github/workflows/new_deploy.yml +++ /dev/null @@ -1,47 +0,0 @@ -name: 'new deploy prod server' - -on: - workflow_dispatch: - -jobs: - deploy: - runs-on: ubuntu-latest - steps: - - name: run on server - uses: garygrossgarten/github-action-ssh@release - with: - host: ${{ secrets.SERVER_HOST }} - username: ${{ secrets.SERVER_USER }} - password: ${{ secrets.SERVER_PASSWORD }} - command: | - cd /home/app/new_procollab_deploy && - git pull origin master && - - rm -f .env && - touch .env && - - echo "DJANGO_SECRET_KEY=${{ secrets.DJANGO_SECRET_KEY }}" >> .env && - - echo "DATABASE_NAME=${{ secrets.DATABASE_NAME }}" >> .env && - echo "DATABASE_PASSWORD=${{ secrets.DATABASE_PASSWORD }}" >> .env && - echo "DATABASE_USER=${{ secrets.DATABASE_USER }}" >> .env && - echo "DATABASE_HOST=${{ secrets.DATABASE_HOST }}" >> .env && - echo "DATABASE_PORT=${{ secrets.DATABASE_PORT }}" >> .env && - - echo "EMAIL_USER=${{ secrets.EMAIL_USER }}" >> .env && - echo "EMAIL_PASSWORD=${{ secrets.EMAIL_PASSWORD }}" >> .env && - echo "EMAIL_HOST=${{ secrets.EMAIL_HOST }}" >> .env && - echo "EMAIL_PORT=${{ secrets.EMAIL_PORT }}" >> .env && - echo "SELECTEL_ACCOUNT_ID=${{ secrets.SELECTEL_ACCOUNT_ID }}" >> .env && - echo "SELECTEL_CONTAINER_NAME=${{ secrets.SELECTEL_CONTAINER_NAME }}" >> .env && - echo "SELECTEL_CONTAINER_PASSWORD=${{ secrets.SELECTEL_CONTAINER_PASSWORD }}" >> .env && - echo "SELECTEL_CONTAINER_USERNAME=${{ secrets.SELECTEL_CONTAINER_USERNAME }}" >> .env && - - echo "CLICKUP_API_TOKEN=${{ secrets.CLICKUP_API_TOKEN }}" >> .env && - echo "CLICKUP_SPACE_ID=${{ secrets.CLICKUP_SPACE_ID }}" >> .env && - - echo "SENTRY_DSN=${{ secrets.SENTRY_DSN }}" >> .env && - - echo "UNISENDER_GO_API_KEY=${{ secrets.UNISENDER_GO_API_KEY }}" >> .env && - - docker compose -f docker-compose.prod-ci.yml -p prod up -d --build diff --git a/.github/workflows/release-ci.yml b/.github/workflows/release-ci.yml index 2ff0f54d..c0377569 100644 --- a/.github/workflows/release-ci.yml +++ b/.github/workflows/release-ci.yml @@ -1,4 +1,4 @@ -name: 'Build and Deploy server' +name: Release Prod on: release: @@ -7,7 +7,7 @@ on: jobs: test: - name: 'Test before deploy' + name: Tests runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 @@ -46,7 +46,7 @@ jobs: DEBUG: True build: - name: 'Build & Publish' + name: Build Image runs-on: ubuntu-latest needs: [ test ] steps: @@ -86,11 +86,12 @@ jobs: cache-to: type=gha,mode=max tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} - run: + deploy: + name: Deploy runs-on: ubuntu-latest needs: [ build ] steps: - - name: run on server + - name: Deploy to server uses: garygrossgarten/github-action-ssh@release with: host: ${{ secrets.SERVER_HOST }} @@ -113,20 +114,12 @@ jobs: echo "DATABASE_HOST=${{ secrets.DATABASE_HOST }}" >> .env && echo "DATABASE_PORT=${{ secrets.DATABASE_PORT }}" >> .env && - echo "EMAIL_USER=${{ secrets.EMAIL_USER }}" >> .env && - echo "EMAIL_PASSWORD=${{ secrets.EMAIL_PASSWORD }}" >> .env && - echo "EMAIL_HOST=${{ secrets.EMAIL_HOST }}" >> .env && - echo "EMAIL_PORT=${{ secrets.EMAIL_PORT }}" >> .env && echo "SELECTEL_ACCOUNT_ID=${{ secrets.SELECTEL_ACCOUNT_ID }}" >> .env && echo "SELECTEL_CONTAINER_NAME=${{ secrets.SELECTEL_CONTAINER_NAME }}" >> .env && echo "SELECTEL_CONTAINER_PASSWORD=${{ secrets.SELECTEL_CONTAINER_PASSWORD }}" >> .env && echo "SELECTEL_CONTAINER_USERNAME=${{ secrets.SELECTEL_CONTAINER_USERNAME }}" >> .env && - - echo "CLICKUP_API_TOKEN=${{ secrets.CLICKUP_API_TOKEN }}" >> .env && - echo "CLICKUP_SPACE_ID=${{ secrets.CLICKUP_SPACE_ID }}" >> .env && - - echo "SENTRY_DSN=${{ secrets.SENTRY_DSN }}" >> .env && + echo "EMAIL_USER=${{ secrets.EMAIL_USER }}" >> .env && echo "UNISENDER_GO_API_KEY=${{ secrets.UNISENDER_GO_API_KEY }}" >> .env && docker compose -f docker-compose.prod-ci.yml -p prod up -d diff --git a/deploy/nginx/host/dev/dev.procollab.ru b/deploy/nginx/host/dev/dev.procollab.ru new file mode 100644 index 00000000..209fb6ca --- /dev/null +++ b/deploy/nginx/host/dev/dev.procollab.ru @@ -0,0 +1,26 @@ +server { + listen 80; + server_name dev.procollab.ru; + + location ^~ /.well-known/acme-challenge/ { + root /var/www/certbot; + default_type "text/plain"; + try_files $uri =404; + } + + location / { + return 301 https://$host$request_uri; + } +} + +server { + listen 443 ssl; + server_name dev.procollab.ru; + + ssl_certificate /etc/letsencrypt/live/dev.procollab.ru-0001/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/dev.procollab.ru-0001/privkey.pem; + + location / { + include /etc/nginx/procollab/includes/proxy_app.inc; + } +} diff --git a/deploy/nginx/host/includes/proxy_app.inc b/deploy/nginx/host/includes/proxy_app.inc new file mode 100644 index 00000000..dda1da81 --- /dev/null +++ b/deploy/nginx/host/includes/proxy_app.inc @@ -0,0 +1,15 @@ +proxy_pass http://127.0.0.1:8000; + +proxy_http_version 1.1; +proxy_set_header Upgrade $http_upgrade; +proxy_set_header Connection "upgrade"; + +proxy_set_header Host $host; +proxy_set_header X-Real-IP $remote_addr; +proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; +proxy_set_header X-Forwarded-Proto $scheme; + +proxy_read_timeout 600s; +proxy_send_timeout 600s; +proxy_connect_timeout 60s; +proxy_buffering off; diff --git a/docker-compose.dev-ci.yml b/docker-compose.dev-ci.yml index d83371f2..fb2504c9 100644 --- a/docker-compose.dev-ci.yml +++ b/docker-compose.dev-ci.yml @@ -16,51 +16,6 @@ services: ports: - "127.0.0.1:8000:8000" - grafana: - image: grafana/grafana:latest - restart: unless-stopped - expose: - - 3000 - volumes: - - grafana-data:/var/lib/grafana - - grafana-configs:/etc/grafana - environment: - - GF_SERVER_ROOT_URL=%(protocol)s://%(domain)s:%(http_port)s/grafana - - GF_SERVER_SERVE_FROM_SUB_PATH=true - - prometheus: - image: prom/prometheus:v2.36.0 - restart: unless-stopped - expose: - - 9090 - volumes: - - prom-data:/prometheus - - ./prometheus:/etc/prometheus - - #nginx: - # restart: unless-stopped - # build: ./nginx - # depends_on: - # - web - # ports: - # - 8000:80 - - loki: - image: grafana/loki:2.9.0 - restart: unless-stopped - ports: - - "3100:3100" - command: -config.file=/etc/loki/local-config.yaml - - promtail: - image: grafana/promtail:2.9.0 - restart: unless-stopped - volumes: - - /var/log:/var/log - - ./promtail:/etc/promtail - - ./log:/procollab/log - command: -config.file=/etc/promtail/config.yml - redis: image: redis:latest restart: unless-stopped @@ -85,12 +40,5 @@ services: - web volumes: - .:/procollab - volumes: - grafana-data: - grafana-configs: - prom-data: - prom-configs: - log: - promtail: redis-data: diff --git a/docs/readme.md b/docs/readme.md index 782c3799..054001fe 100644 --- a/docs/readme.md +++ b/docs/readme.md @@ -5,4 +5,3 @@ - [redoc](https://api.procollab.ru/redoc) ## [WebSockets для чатов](/docs/chats.md) - diff --git a/partner_programs/views.py b/partner_programs/views.py index 5f16c713..af312f75 100644 --- a/partner_programs/views.py +++ b/partner_programs/views.py @@ -301,7 +301,7 @@ def post(self, request, *args, **kwargs): "birthday": date_to_iso(data.get("birthday", "01-01-1900")), "is_active": True, # bypass email verification "onboarding_stage": None, # bypass onboarding - "verification_date": timezone.now(), # bypass ClickUp verification + "verification_date": timezone.now(), # bypass manual verification **{field_name: data.get(field_name, "") for field_name in user_fields}, }, ) diff --git a/users/services/verification.py b/users/services/verification.py deleted file mode 100644 index 5a26f120..00000000 --- a/users/services/verification.py +++ /dev/null @@ -1,64 +0,0 @@ -""" -A verification service that uses ClickUp API for creating tasks - -When the user confirms his email, the service creates a task in the ClickUp Space with information -about the user so that the moderator can manually check the information about him -""" - -import requests -from decouple import config -from django.contrib.auth import get_user_model - -User = get_user_model() - - -class VerificationTasks: - instance = None - __TOKEN = config("CLICKUP_API_TOKEN", default="default-api-key", cast=str) - __CLICKUP_SPACE_ID = config("CLICKUP_SPACE_ID", default=0, cast=int) - - @classmethod - def create(cls, user: User): - data = cls._collect_data(user) - cls._send_request(data) - - @classmethod - def _collect_data(cls, user: User): - # todo DEBUG mode - link_to_platform = f"https://app.procollab.ru/office/profile/{user.pk}/" - link_to_admin_panel = ( - f"https://api.procollab.ru/admin/users/customuser/{user.pk}/change/" - ) - - priority = 3 # normal - if user.user_type != User.MEMBER: - priority = 1 # urgent - - description = f"Профиль в админке: {link_to_admin_panel}\nПрофиль на платформе: {link_to_platform}" - name = f"{user.pk}: {user.first_name} {user.last_name}" - - return { - "name": name, - "priority": priority, - "description": description, - } - - @classmethod - def _send_request(cls, data): - try: - url = f"https://api.clickup.com/api/v2/list/{cls.__CLICKUP_SPACE_ID}/task/" - requests.post( - url, - data=data, - headers={ - "Authorization": cls.__TOKEN, - }, - ).json() - except Exception: - # fixme - pass - - def __new__(cls, *args, **kwargs): - if not hasattr(cls, "instance"): - cls.instance = super().__new__(cls) - return cls.instance diff --git a/users/views.py b/users/views.py index 4a59332f..dfa7fc88 100644 --- a/users/views.py +++ b/users/views.py @@ -46,7 +46,6 @@ VERBOSE_ROLE_TYPES, VERBOSE_USER_TYPES, VERIFY_EMAIL_REDIRECT_URL, - OnboardingStage, ) from users.helpers import check_related_fields_update, force_verify_user, verify_email from users.models import LikesOnProject, UserAchievement, UserSkillConfirmation @@ -76,7 +75,6 @@ from .pagination import UsersPagination from .schema import SKILL_PK_PARAM, USER_PK_PARAM from .services.cv_data_prepare import UserCVDataPreparerV2 -from .services.verification import VerificationTasks from .tasks import send_mail_cv User = get_user_model() @@ -493,13 +491,6 @@ def put(self, request: Request, pk): status=status.HTTP_400_BAD_REQUEST, data={"error": "Wrong onboarding stage number!"}, ) - # if the user was on the last stage and passed it - if ( - request.user.onboarding_stage == OnboardingStage.account_type.value - and new_stage == OnboardingStage.completed.value - ): - VerificationTasks.create(request.user) - request.user.onboarding_stage = new_stage request.user.save()