Skip to content

Merge pull request #639 from PROCOLLAB-github/devops-structure-rework #413

Merge pull request #639 from PROCOLLAB-github/devops-structure-rework

Merge pull request #639 from PROCOLLAB-github/devops-structure-rework #413

Workflow file for this run

name: Deploy Dev
on:
push:
branches:
- dev
workflow_dispatch:
jobs:
deploy:
name: Deploy
runs-on: ubuntu-latest
steps:
- name: Deploy to server
uses: garygrossgarten/github-action-ssh@release
with:
host: ${{ secrets.DEV_SERVER_HOST }}
username: ${{ secrets.DEV_SERVER_USER }}
password: ${{ secrets.DEV_SERVER_PASSWORD }}
command: |
set -eu
cd /root/api
git fetch --all --tags --prune
git branch -r --contains "${{ github.sha }}" | grep -q 'origin/dev'
git checkout --detach "${{ github.sha }}"
git rev-parse HEAD
export IMAGE_TAG="${{ github.sha }}"
rm -f .env
touch .env
echo "DJANGO_SECRET_KEY=${{ secrets.DEV_DJANGO_SECRET_KEY }}" >> .env
echo "DATABASE_NAME=${{ secrets.DEV_DATABASE_NAME }}" >> .env
echo "DATABASE_PASSWORD=${{ secrets.DEV_DATABASE_PASSWORD }}" >> .env
echo "DATABASE_USER=${{ secrets.DEV_DATABASE_USER }}" >> .env
echo "DATABASE_HOST=${{ secrets.DEV_DATABASE_HOST }}" >> .env
echo "DATABASE_PORT=${{ secrets.DEV_DATABASE_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 "EMAIL_USER=${{ secrets.EMAIL_USER }}" >> .env
echo "UNISENDER_GO_API_KEY=${{ secrets.UNISENDER_GO_API_KEY }}" >> .env
chmod 600 .env
docker compose -f docker-compose.dev-ci.yml config >/dev/null
docker compose -f docker-compose.dev-ci.yml build web &&
docker compose -f docker-compose.dev-ci.yml run --rm web python manage.py migrate &&
docker compose -f docker-compose.dev-ci.yml up -d --force-recreate &&
expected_image="procollab-dev-api:${IMAGE_TAG}" &&
for service in web celerys; do
container="$(docker compose -f docker-compose.dev-ci.yml ps -q "$service")"
if [ -z "$container" ]; then
echo "Service ${service} has no running container" >&2
docker compose -f docker-compose.dev-ci.yml ps >&2 || true
exit 1
fi
actual_image="$(docker inspect -f '{{.Config.Image}}' "$container")"
echo "Service ${service}: container=${container} image=${actual_image}"
if [ "$actual_image" != "$expected_image" ]; then
echo "Service ${service} uses unexpected image: ${actual_image}, expected ${expected_image}" >&2
docker compose -f docker-compose.dev-ci.yml ps >&2 || true
exit 1
fi
done &&
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 &&
if [ "$(id -u)" -eq 0 ]; then
nginx -t &&
systemctl reload nginx
else
sudo nginx -t &&
sudo systemctl reload nginx
fi &&
for attempt in $(seq 1 24); do
root_status="$(curl -s -o /dev/null -w '%{http_code}' https://dev.procollab.ru/ || true)" &&
admin_status="$(curl -s -o /dev/null -w '%{http_code}' https://dev.procollab.ru/admin/login/ || true)" &&
if [ "$root_status" = "401" ] && [ "$admin_status" = "200" ]; then
echo "Smoke check passed on attempt ${attempt}" &&
break
fi
sleep 5
done &&
if [ "$root_status" != "401" ] || [ "$admin_status" != "200" ]; then
echo "Smoke check failed: /=${root_status} /admin/login/=${admin_status}" >&2 &&
exit 1
fi &&
docker compose -f docker-compose.dev-ci.yml ps
celery_status=""
celery_ping=""
celery_container=""
for attempt in $(seq 1 12); do
celery_container="$(docker compose -f docker-compose.dev-ci.yml ps -q celerys 2>/dev/null || true)"
if [ -n "$celery_container" ]; then
celery_status="$(docker inspect -f '{{.State.Status}}' "$celery_container" 2>/dev/null || true)"
else
celery_status="missing"
fi
echo "Celery check attempt ${attempt}: container=${celery_container:-missing} status=${celery_status}"
if [ "$celery_status" = "running" ]; then
celery_ping="$(docker compose -f docker-compose.dev-ci.yml exec -T celerys sh -lc 'celery -A procollab inspect ping --timeout=15' 2>&1 || true)"
printf '%s\n' "$celery_ping"
if printf '%s\n' "$celery_ping" | grep -q 'pong'; then
echo "Celery check passed on attempt ${attempt}"
break
fi
fi
sleep 5
done
if [ "$celery_status" != "running" ] || ! printf '%s\n' "$celery_ping" | grep -q 'pong'; then
echo "Celery check failed: status=${celery_status}" >&2
docker compose -f docker-compose.dev-ci.yml ps >&2 || true
docker compose -f docker-compose.dev-ci.yml logs --tail=200 celerys >&2 || true
docker compose -f docker-compose.dev-ci.yml logs --tail=100 redis >&2 || true
docker compose -f docker-compose.dev-ci.yml logs --tail=100 web >&2 || true
exit 1
fi