diff --git a/.github/workflows/build_and_deploy.yml b/.github/workflows/build_and_deploy.yml new file mode 100644 index 0000000..164775d --- /dev/null +++ b/.github/workflows/build_and_deploy.yml @@ -0,0 +1,95 @@ +name: Build and Deploy Workflow + +on: + push: + branches: + - develop + - main + +env: + REPO_NAME: ${{ github.event.repository.name }} + COMPOSE_PROJECT_NAME: sh_bot_stat_collector + ENVIRONMENT: ${{ github.ref == 'refs/heads/develop' && 'dev' || 'prod' }} + COMPOSE_FILES: ${{ github.ref == 'refs/heads/develop' && '-f docker-compose.yml -f docker-compose.dev.yml' || '-f docker-compose.yml -f docker-compose.prod.yml' }} + TELEGRAM_BOT_TOKEN: ${{ github.ref == 'refs/heads/develop' && secrets.DEV_TELEGRAM_BOT_TOKEN || secrets.PROD_TELEGRAM_BOT_TOKEN }} + +jobs: + build: + runs-on: [self-hosted] + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Build container + uses: appleboy/ssh-action@master + with: + host: ${{ secrets.HOST }} + username: ${{ secrets.USERNAME }} + password: ${{ secrets.PASSWORD }} + key: ${{ secrets.PRIVATE_KEY }} + script: | + cd ./_work/${{ env.REPO_NAME }}/${{ env.REPO_NAME }} + docker compose -p sh_bot_stat_collector_${{ env.ENVIRONMENT }} ${{ env.COMPOSE_FILES }} build --no-cache + + deploy: + needs: build + runs-on: [self-hosted] + steps: + - name: Deploy to server + uses: appleboy/ssh-action@master + env: + DEVELOPER_CHAT_ID: ${{ secrets.DEVELOPER_CHAT_ID }} + SQLITE_DB_FILE_PATH: ${{ secrets.SQLITE_DB_FILE_PATH }} + TELEGRAM_BOT_TOKEN: ${{ env.TELEGRAM_BOT_TOKEN }} + with: + host: ${{ secrets.HOST }} + username: ${{ secrets.USERNAME }} + password: ${{ secrets.PASSWORD }} + key: ${{ secrets.PRIVATE_KEY }} + script: | + cd ./_work/${{ env.REPO_NAME }}/${{ env.REPO_NAME }} + docker compose -p ${{ env.COMPOSE_PROJECT_NAME }}_${{ env.ENVIRONMENT }} ${{ env.COMPOSE_FILES }} up -d --force-recreate; + envs: TELEGRAM_BOT_TOKEN,DEVELOPER_CHAT_ID,SQLITE_DB_FILE_PATH + + deploy-check: + needs: deploy + runs-on: [self-hosted] + steps: + - name: Docker Compose is up + uses: appleboy/ssh-action@master + env: + DEVELOPER_CHAT_ID: ${{ secrets.DEVELOPER_CHAT_ID }} + TELEGRAM_BOT_TOKEN: ${{ env.TELEGRAM_BOT_TOKEN }} + with: + host: ${{ secrets.HOST }} + username: ${{ secrets.USERNAME }} + password: ${{ secrets.PASSWORD }} + key: ${{ secrets.PRIVATE_KEY }} + script: | + sleep 5; # Allow services to start + service_name=$(docker compose -p ${{ env.COMPOSE_PROJECT_NAME }}_${{ env.ENVIRONMENT }} ${{ env.COMPOSE_FILES }} ps --services); + for service in $service_name; do + if ! docker compose -p ${{ env.COMPOSE_PROJECT_NAME }}_${{ env.ENVIRONMENT }} ${{ env.COMPOSE_FILES }} ps | grep -q "$service.* Up"; then + echo "$service not running as expected."; + exit 1; + fi; + done; + envs: TELEGRAM_BOT_TOKEN,DEVELOPER_CHAT_ID + + notification: + needs: deploy-check + runs-on: [self-hosted] + steps: + - name: Notify developer + uses: appleboy/ssh-action@master + env: + DEVELOPER_CHAT_ID: ${{ secrets.DEVELOPER_CHAT_ID }} + TELEGRAM_BOT_TOKEN: ${{ env.TELEGRAM_BOT_TOKEN }} + with: + host: ${{ secrets.HOST }} + username: ${{ secrets.USERNAME }} + password: ${{ secrets.PASSWORD }} + key: ${{ secrets.PRIVATE_KEY }} + script: | + curl -s -X POST https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage -d chat_id=${DEVELOPER_CHAT_ID} -d text="Successfully deployed SHA: ${{ github.sha }} to ${{ env.ENVIRONMENT }} environment" + envs: TELEGRAM_BOT_TOKEN,DEVELOPER_CHAT_ID \ No newline at end of file diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml deleted file mode 100644 index d0d98cc..0000000 --- a/.github/workflows/deploy.yml +++ /dev/null @@ -1,47 +0,0 @@ -name: CI/CD with Docker Compose -env: - REPO_NAME: ${{ github.event.repository.name }} - -on: - push: - branches: - - main - -jobs: - build: - runs-on: [self-hosted] - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - name: executing remote ssh commands using password - uses: appleboy/ssh-action@master - with: - host: ${{ secrets.HOST }} - username: ${{ secrets.USERNAME }} - password: ${{ secrets.PASSWORD }} - key: ${{ secrets.PRIVATE_KEY }} - script: | - cd ./_work/${{ env.REPO_NAME }}/${{ env.REPO_NAME }} - docker compose build --no-cache - - deploy: - needs: [build] - runs-on: [self-hosted] - steps: - - name: SSH into production server and deploy - uses: appleboy/ssh-action@master - env: - TELEGRAM_BOT_TOKEN: ${{ secrets.PROD_TELEGRAM_BOT_TOKEN }} - DEVELOPER_CHAT_ID: ${{ secrets.DEVELOPER_CHAT_ID }} - SQLITE_DB_FILE_PATH: ${{ vars.SQLITE_DB_FILE_PATH }} - with: - host: ${{ secrets.HOST }} - username: ${{ secrets.USERNAME }} - password: ${{ secrets.PASSWORD }} - key: ${{ secrets.PRIVATE_KEY }} - script: | - cd ./_work/${{ env.REPO_NAME }}/${{ env.REPO_NAME }} - docker compose down - docker compose up -d - docker compose ps - envs: TELEGRAM_BOT_TOKEN,DEVELOPER_CHAT_ID,SQLITE_DB_FILE_PATH \ No newline at end of file diff --git a/.github/workflows/develop.yml b/.github/workflows/develop.yml deleted file mode 100644 index 2ca6182..0000000 --- a/.github/workflows/develop.yml +++ /dev/null @@ -1,47 +0,0 @@ -name: CI/CD with Docker Compose -env: - REPO_NAME: ${{ github.event.repository.name }} - -on: - push: - branches: - - develop - -jobs: - build: - runs-on: [self-hosted] - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - name: executing remote ssh commands using password - uses: appleboy/ssh-action@master - with: - host: ${{ secrets.HOST }} - username: ${{ secrets.USERNAME }} - password: ${{ secrets.PASSWORD }} - key: ${{ secrets.PRIVATE_KEY }} - script: | - cd ./_work/${{ env.REPO_NAME }}/${{ env.REPO_NAME }} - docker compose build --no-cache - - deploy: - needs: [build] - runs-on: [self-hosted] - steps: - - name: SSH into production server and deploy - uses: appleboy/ssh-action@master - env: - TELEGRAM_BOT_TOKEN: ${{ secrets.DEV_TELEGRAM_BOT_TOKEN }} - DEVELOPER_CHAT_ID: ${{ secrets.DEVELOPER_CHAT_ID }} - SQLITE_DB_FILE_PATH: ${{ vars.SQLITE_DB_FILE_PATH }} - with: - host: ${{ secrets.HOST }} - username: ${{ secrets.USERNAME }} - password: ${{ secrets.PASSWORD }} - key: ${{ secrets.PRIVATE_KEY }} - script: | - cd ./_work/${{ env.REPO_NAME }}/${{ env.REPO_NAME }} - docker compose down - docker compose up -d - docker compose ps - envs: TELEGRAM_BOT_TOKEN,DEVELOPER_CHAT_ID,SQLITE_DB_FILE_PATH \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 663739e..f640668 100644 --- a/Dockerfile +++ b/Dockerfile @@ -37,11 +37,17 @@ RUN poetry install --no-root ############################################### # Production Image ############################################### + FROM base-image as production -RUN apt-get update && \ - apt-get install -y python3-cairosvg +RUN apt-get update \ + && apt-get install --no-install-recommends -y \ + libffi-dev \ + libcairo2 \ + python3-cairosvg + COPY --from=builder-base $PYSETUP_PATH $PYSETUP_PATH + ARG PYTHONPATH=/service ENV PYTHONPATH=$PYTHONPATH \ POETRY_PROJECT_PATH=$PYTHONPATH/pyproject.toml diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml new file mode 100644 index 0000000..daf2602 --- /dev/null +++ b/docker-compose.dev.yml @@ -0,0 +1,8 @@ +version: '3.8' + +services: + bot: + volumes: + - sqlite_data_dev:/database +volumes: + sqlite_data_dev: \ No newline at end of file diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml new file mode 100644 index 0000000..ee86948 --- /dev/null +++ b/docker-compose.prod.yml @@ -0,0 +1,11 @@ +version: '3.8' + +services: + bot: + volumes: + - sqlite_data:/database + +volumes: + sqlite_data: + +# Only define services specific to development or production in their respective override files diff --git a/docker-compose.yaml b/docker-compose.yaml deleted file mode 100644 index 498bd90..0000000 --- a/docker-compose.yaml +++ /dev/null @@ -1,36 +0,0 @@ -version: '3' - -services: - bot: - build: . - environment: - - SQLITE_DB_FILE_PATH=/database/db.sqlite - - TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN} - - DEVELOPER_CHAT_ID=${DEVELOPER_CHAT_ID} - - TZ=GMT - volumes: - - sqlite_data:/database - entrypoint: ["/bin/sh", "-c"] - command: - - | - python -m sqlite3 ${SQLITE_DB_FILE_PATH} < src/sql/init.sql; - python src/__main__.py; - restart: always - - sqlitebrowser: - image: linuxserver/sqlitebrowser - ports: - - "3000:3000" - environment: - - PUID=1000 - - PGID=1000 - - TZ=GMT - - ENABLE_UWSGI=true - volumes: - - sqlite_data:/database - profiles: - - sqlitebrowser - restart: unless-stopped - -volumes: - sqlite_data: \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..f24d12d --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,18 @@ +version: '3.8' + +services: + bot: + build: . + environment: + SQLITE_DB_FILE_PATH: /database/db.sqlite + TELEGRAM_BOT_TOKEN: ${TELEGRAM_BOT_TOKEN} + DEVELOPER_CHAT_ID: ${DEVELOPER_CHAT_ID} + TZ: ${TZ-GMT} # Default to GMT if TZ is not specified + entrypoint: ["/bin/sh", "-c"] + command: + - | + python -m sqlite3 ${SQLITE_DB_FILE_PATH} < src/sql/init.sql; + python src/__main__.py; + restart: always + +# Only define services specific to development or production in their respective override files