--- kind: pipeline type: docker name: smartsoltech-ci platform: os: linux arch: amd64 services: - name: postgres image: postgres:17-alpine environment: POSTGRES_DB: smartsoltech_test POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres POSTGRES_HOST_AUTH_METHOD: trust ports: - 5432 - name: redis image: redis:7-alpine ports: - 6379 steps: - name: code-quality image: python:3.10-slim environment: DATABASE_URL: postgresql://postgres:postgres@postgres:5432/smartsoltech_test commands: - apt-get update && apt-get install -y git - pip install --upgrade pip - pip install flake8 black isort bandit safety - echo "Checking code quality..." - flake8 smartsoltech/ --max-line-length=88 --exclude=migrations,staticfiles --ignore=E203,W503 || true - echo "Checking code formatting..." - black --check smartsoltech/ --line-length=88 --target-version=py310 || true - echo "Checking imports..." - isort --check-only smartsoltech/ --profile=black || true - echo "Security scan..." - bandit -r smartsoltech/ -x "*/migrations/*,*/staticfiles/*" -ll || true - echo "Checking dependencies..." - safety check --file requirements.txt --ignore=70612 || true - name: install-dependencies image: python:3.10-slim commands: - apt-get update && apt-get install -y libpq-dev gcc git curl - pip install --upgrade pip - pip install -r requirements.txt - pip install coverage pytest-django pytest-cov - echo "Dependencies installed" depends_on: - code-quality - name: database-tests image: python:3.10-slim environment: DATABASE_URL: postgresql://postgres:postgres@postgres:5432/smartsoltech_test SECRET_KEY: test-secret-key-for-ci-very-long-and-secure-key-12345 DEBUG: "False" ALLOWED_HOSTS: localhost,127.0.0.1 DJANGO_SETTINGS_MODULE: smartsoltech.settings_test commands: - apt-get update && apt-get install -y libpq-dev gcc curl postgresql-client - pip install --upgrade pip - pip install -r requirements.txt - echo "Waiting for PostgreSQL..." - sleep 15 - echo "Checking database connection..." - until pg_isready -h postgres -p 5432 -U postgres; do echo "Waiting for postgres..."; sleep 2; done - echo "Creating test database..." - PGPASSWORD=postgres createdb -h postgres -U postgres smartsoltech_test || echo "Database already exists" - echo "Checking migrations..." - cd smartsoltech - python manage.py check --settings=smartsoltech.settings_test - python manage.py makemigrations --check --dry-run --settings=smartsoltech.settings_test - python manage.py migrate --settings=smartsoltech.settings_test - echo "Database setup completed" depends_on: - install-dependencies - name: unit-tests image: python:3.10-slim environment: DATABASE_URL: postgresql://postgres:postgres@postgres:5432/smartsoltech_test SECRET_KEY: test-secret-key-for-ci-very-long-and-secure-key-12345 DEBUG: "False" ALLOWED_HOSTS: localhost,127.0.0.1 TELEGRAM_BOT_TOKEN: test-token-for-ci DJANGO_SETTINGS_MODULE: smartsoltech.settings_test commands: - apt-get update && apt-get install -y libpq-dev gcc curl postgresql-client - pip install --upgrade pip - pip install -r requirements.txt - echo "Waiting for PostgreSQL..." - until pg_isready -h postgres -p 5432 -U postgres; do echo "Waiting for postgres..."; sleep 2; done - cd smartsoltech - echo "Running unit tests..." - python manage.py test --verbosity=2 --settings=smartsoltech.settings_test --keepdb - echo "Generating coverage report..." - coverage run --source='.' manage.py test --settings=smartsoltech.settings_test --keepdb - coverage report --show-missing - coverage xml - echo "Unit tests completed successfully" depends_on: - database-tests - name: build-docker-image image: docker:24-dind volumes: - name: docker-sock path: /var/run/docker.sock commands: - echo "Building Docker image..." - docker build -t smartsoltech:latest . - echo "Docker image built successfully" depends_on: - unit-tests - name: docker-compose-tests image: docker/compose:latest volumes: - name: docker-sock path: /var/run/docker.sock commands: - echo "Running Docker Compose tests..." - apk add --no-cache curl - docker-compose -f docker-compose.test.yml build - docker-compose -f docker-compose.test.yml up --abort-on-container-exit --exit-code-from django_test - docker-compose -f docker-compose.test.yml down -v - echo "Docker tests completed" depends_on: - build-docker-image - name: security-scan image: aquasec/trivy:latest commands: - echo "Security scanning Docker image..." - trivy image --exit-code 0 --severity HIGH,CRITICAL --no-progress smartsoltech:latest - echo "Security scan completed" depends_on: - docker-compose-tests - name: notify-success image: plugins/webhook settings: urls: from_secret: telegram_webhook_url content_type: application/json template: | { "chat_id": "${TELEGRAM_CHAT_ID}", "text": "โœ… *SmartSolTech CI/CD*\n\nBuild completed successfully!\n\n๐Ÿ“ *Commit:* `${DRONE_COMMIT_SHA:0:8}`\n๐Ÿ‘ค *Author:* ${DRONE_COMMIT_AUTHOR}\n๐ŸŒฟ *Branch:* ${DRONE_BRANCH}\nโฑ *Time:* ${DRONE_BUILD_FINISHED}\n\n๐Ÿ”— [Details](${DRONE_BUILD_LINK})", "parse_mode": "Markdown" } environment: TELEGRAM_CHAT_ID: from_secret: telegram_chat_id when: status: - success depends_on: - security-scan - name: notify-failure image: plugins/webhook settings: urls: from_secret: telegram_webhook_url content_type: application/json template: | { "chat_id": "${TELEGRAM_CHAT_ID}", "text": "โŒ *SmartSolTech CI/CD*\n\nBuild failed!\n\n๐Ÿ“ *Commit:* `${DRONE_COMMIT_SHA:0:8}`\n๐Ÿ‘ค *Author:* ${DRONE_COMMIT_AUTHOR}\n๐ŸŒฟ *Branch:* ${DRONE_BRANCH}\nโฑ *Time:* ${DRONE_BUILD_FINISHED}\n\n๐Ÿ”— [Logs](${DRONE_BUILD_LINK})", "parse_mode": "Markdown" } environment: TELEGRAM_CHAT_ID: from_secret: telegram_chat_id when: status: - failure depends_on: - security-scan volumes: - name: docker-sock host: path: /var/run/docker.sock trigger: branch: - master - main - develop - feature/* event: - push - pull_request --- kind: pipeline type: docker name: production-deploy platform: os: linux arch: amd64 steps: - name: deploy-production image: docker:24-dind volumes: - name: docker-sock path: /var/run/docker.sock environment: PROD_HOST: from_secret: production_host PROD_USER: from_secret: production_user PROD_KEY: from_secret: production_ssh_key commands: - echo "Deploying to production..." - apk add --no-cache openssh-client git - mkdir -p ~/.ssh - echo "$PROD_KEY" > ~/.ssh/id_rsa - chmod 600 ~/.ssh/id_rsa - ssh-keyscan -H $PROD_HOST >> ~/.ssh/known_hosts - ssh $PROD_USER@$PROD_HOST "cd /opt/smartsoltech && git pull origin master && ./bin/update" - echo "Production deployment completed" - name: notify-production-success image: plugins/webhook settings: urls: from_secret: telegram_webhook_url content_type: application/json template: | { "chat_id": "${TELEGRAM_CHAT_ID}", "text": "๐ŸŽ‰ *SmartSolTech Production*\n\nโœ… Production deployment completed!\n\n๐Ÿ“ *Version:* `${DRONE_TAG}`\n๐Ÿ‘ค *Author:* ${DRONE_COMMIT_AUTHOR}\nโฑ *Time:* ${DRONE_BUILD_FINISHED}\n\n๐ŸŒ [Website](https://smartsoltech.kr)", "parse_mode": "Markdown" } environment: TELEGRAM_CHAT_ID: from_secret: telegram_chat_id depends_on: - deploy-production - name: notify-production-failure image: plugins/webhook settings: urls: from_secret: telegram_webhook_url content_type: application/json template: | { "chat_id": "${TELEGRAM_CHAT_ID}", "text": "๐Ÿšจ *SmartSolTech Production*\n\nโŒ Production deployment failed!\n\n๐Ÿ“ *Version:* `${DRONE_TAG}`\n๐Ÿ‘ค *Author:* ${DRONE_COMMIT_AUTHOR}\nโฑ *Time:* ${DRONE_BUILD_FINISHED}\n\n๐Ÿ”— [Logs](${DRONE_BUILD_LINK})", "parse_mode": "Markdown" } environment: TELEGRAM_CHAT_ID: from_secret: telegram_chat_id when: status: - failure depends_on: - deploy-production volumes: - name: docker-sock host: path: /var/run/docker.sock trigger: event: - tag ref: - refs/tags/v* depends_on: - smartsoltech-ci --- kind: pipeline type: docker name: maintenance platform: os: linux arch: amd64 steps: - name: cleanup-docker image: docker:24-dind volumes: - name: docker-sock path: /var/run/docker.sock commands: - echo "Docker cleanup..." - docker system prune -af --volumes - docker image prune -af - echo "Docker cleanup completed" - name: backup-database image: postgres:17-alpine environment: PGHOST: from_secret: db_host PGUSER: from_secret: db_user PGPASSWORD: from_secret: db_password PGDATABASE: from_secret: db_name BACKUP_PATH: from_secret: backup_path commands: - echo "Creating database backup..." - mkdir -p /backups - pg_dump -h $PGHOST -U $PGUSER -d $PGDATABASE --no-password > /backups/backup_$(date +%Y%m%d_%H%M%S).sql - echo "Database backup created" - name: notify-maintenance image: plugins/webhook settings: urls: from_secret: telegram_webhook_url content_type: application/json template: | { "chat_id": "${TELEGRAM_CHAT_ID}", "text": "๐Ÿ›  *SmartSolTech Maintenance*\n\nโœ… Scheduled maintenance completed!\n\n๐Ÿงน Docker cleanup\n๐Ÿ’พ Database backup\nโฑ *Time:* ${DRONE_BUILD_FINISHED}", "parse_mode": "Markdown" } environment: TELEGRAM_CHAT_ID: from_secret: telegram_chat_id depends_on: - cleanup-docker - backup-database volumes: - name: docker-sock host: path: /var/run/docker.sock trigger: event: - cron cron: - nightly_maintenance