Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 45 additions & 1 deletion .github/workflows/dev-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ jobs:

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 --remove-orphans &&

install -d /etc/nginx/procollab/includes &&
Expand All @@ -63,4 +64,47 @@ jobs:
else
sudo nginx -t &&
sudo systemctl reload nginx
fi
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 &&

celery_status="" &&
celery_ping="" &&
for attempt in $(seq 1 24); do
celery_status="$(docker inspect -f '{{.State.Status}}' api_celery 2>/dev/null || true)" &&
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 -d \"celery@$(hostname)\"' 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" ]; then
echo "Celery container is not running: ${celery_status}" >&2 &&
exit 1
fi &&

printf '%s\n' "$celery_ping" | grep -q 'pong' || {
echo "Celery ping failed" >&2
exit 1
}
118 changes: 77 additions & 41 deletions .github/workflows/release-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,45 @@ on:
type: string

jobs:
prepare:
name: Resolve Release Ref
runs-on: ubuntu-latest
outputs:
image_tag: ${{ steps.vars.outputs.image_tag }}
deploy_ref: ${{ steps.vars.outputs.deploy_ref }}
steps:
- name: Resolve image tag and deploy ref
id: vars
run: |
if [ "${{ github.event_name }}" = "release" ]; then
image_tag='${{ github.event.release.tag_name }}'
deploy_ref='${{ github.event.release.tag_name }}'
else
image_tag='${{ github.event.inputs.image_tag }}'
deploy_ref='${{ github.event.inputs.deploy_ref }}'
fi

if [ -z "$image_tag" ]; then
echo "IMAGE_TAG is empty" >&2
exit 1
fi

if [ -z "$deploy_ref" ]; then
echo "DEPLOY_REF is empty" >&2
exit 1
fi

echo "image_tag=$image_tag" >> "$GITHUB_OUTPUT"
echo "deploy_ref=$deploy_ref" >> "$GITHUB_OUTPUT"

test:
name: Tests
runs-on: ubuntu-latest
needs: [ prepare ]
steps:
- uses: actions/checkout@v3
with:
ref: ${{ needs.prepare.outputs.deploy_ref }}

- name: Set up Python 3.11
uses: actions/setup-python@v4
Expand Down Expand Up @@ -57,39 +91,15 @@ jobs:
build:
name: Build Image
runs-on: ubuntu-latest
needs: [ test ]
needs: [ prepare, test ]
outputs:
image_tag: ${{ steps.vars.outputs.image_tag }}
deploy_ref: ${{ steps.vars.outputs.deploy_ref }}
image_tag: ${{ needs.prepare.outputs.image_tag }}
deploy_ref: ${{ needs.prepare.outputs.deploy_ref }}
steps:
- name: "Checkout repository"
uses: actions/checkout@v3
with:
ref: ${{ github.event_name == 'release' && github.event.release.tag_name || github.event.inputs.deploy_ref }}

- name: Resolve image tag
id: vars
run: |
if [ "${{ github.event_name }}" = "release" ]; then
image_tag='${{ github.event.release.tag_name }}'
deploy_ref='${{ github.event.release.tag_name }}'
else
image_tag='${{ github.event.inputs.image_tag }}'
deploy_ref='${{ github.event.inputs.deploy_ref }}'
fi

if [ -z "$image_tag" ]; then
echo "IMAGE_TAG is empty" >&2
exit 1
fi

if [ -z "$deploy_ref" ]; then
echo "DEPLOY_REF is empty" >&2
exit 1
fi

echo "image_tag=$image_tag" >> "$GITHUB_OUTPUT"
echo "deploy_ref=$deploy_ref" >> "$GITHUB_OUTPUT"
ref: ${{ needs.prepare.outputs.deploy_ref }}

- name: "Set up QEMU"
uses: docker/setup-qemu-action@v3
Expand All @@ -110,7 +120,7 @@ jobs:
with:
images: ghcr.io/procollab-github/api
tags: |
type=raw,value=${{ steps.vars.outputs.image_tag }}
type=raw,value=${{ needs.prepare.outputs.image_tag }}
- name: Build and push container
uses: docker/build-push-action@v5
with:
Expand All @@ -124,7 +134,7 @@ jobs:
deploy:
name: Deploy
runs-on: ubuntu-latest
needs: [ build ]
needs: [ prepare, build ]
steps:
- name: Deploy to server
uses: garygrossgarten/github-action-ssh@release
Expand All @@ -135,8 +145,8 @@ jobs:
command: |
set -eu

export IMAGE_TAG="${{ needs.build.outputs.image_tag }}"
export DEPLOY_REF="${{ needs.build.outputs.deploy_ref }}"
export IMAGE_TAG="${{ needs.prepare.outputs.image_tag }}"
export DEPLOY_REF="${{ needs.prepare.outputs.deploy_ref }}"
echo "Deploying IMAGE_TAG=${IMAGE_TAG} from DEPLOY_REF=${DEPLOY_REF}"

if [ "$(id -un)" = "app" ]; then
Expand All @@ -150,10 +160,6 @@ jobs:
fi

cd /home/app/procollab-backend
docker container prune -f
docker image prune -a -f
docker compose -f docker-compose.prod-ci.yml -p prod pull

rm -f .env
touch .env

Expand All @@ -175,7 +181,9 @@ jobs:

chmod 600 .env
docker compose -f docker-compose.prod-ci.yml -p prod config >/dev/null
docker compose -f docker-compose.prod-ci.yml -p prod pull

docker compose -f docker-compose.prod-ci.yml -p prod run --rm web python manage.py migrate
docker compose -f docker-compose.prod-ci.yml -p prod up -d --remove-orphans
if [ "$(id -u)" -eq 0 ]; then
nginx -t
Expand All @@ -186,16 +194,44 @@ jobs:
fi

for attempt in $(seq 1 24); do
root_status="$(curl -k -s -o /dev/null -w '%{http_code}' https://api.procollab.ru/ || true)"
admin_status="$(curl -k -s -o /dev/null -w '%{http_code}' https://api.procollab.ru/admin/login/ || true)"
root_status="$(curl -s -o /dev/null -w '%{http_code}' https://api.procollab.ru/ || true)"
admin_status="$(curl -s -o /dev/null -w '%{http_code}' https://api.procollab.ru/admin/login/ || true)"

if [ "$root_status" = "401" ] && [ "$admin_status" = "200" ]; then
echo "Smoke check passed on attempt ${attempt}"
exit 0
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

celery_status=""
celery_ping=""
for attempt in $(seq 1 24); do
celery_status="$(docker inspect -f '{{.State.Status}}' api_celery 2>/dev/null || true)"
if [ "$celery_status" = "running" ]; then
celery_ping="$(docker compose -f docker-compose.prod-ci.yml -p prod exec -T celerys sh -lc 'celery -A procollab inspect ping -d \"celery@$(hostname)\"' 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

echo "Smoke check failed: /=${root_status} /admin/login/=${admin_status}"
exit 1
if [ "$celery_status" != "running" ]; then
echo "Celery container is not running: ${celery_status}" >&2
exit 1
fi

printf '%s\n' "$celery_ping" | grep -q 'pong' || {
echo "Celery ping failed" >&2
exit 1
}
11 changes: 9 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,12 @@ RUN mkdir /procollab/static

COPY . /procollab/

CMD ["bash", "./scripts/startup.sh"]

RUN DJANGO_SECRET_KEY=build-time-secret \
DATABASE_NAME=postgres \
DATABASE_USER=postgres \
DATABASE_PASSWORD=postgres \
DATABASE_HOST=localhost \
DATABASE_PORT=5432 \
python manage.py collectstatic --no-input

CMD ["daphne", "-b", "0.0.0.0", "-p", "8000", "procollab.asgi:application"]
2 changes: 1 addition & 1 deletion docker-compose.dev-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ services:
- "127.0.0.1:8000:8000"

redis:
image: redis:latest
image: redis:7.2.5
restart: unless-stopped
expose:
- 6379
Expand Down
2 changes: 1 addition & 1 deletion docker-compose.prod-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ services:
ports:
- "127.0.0.1:8000:8000"
redis:
image: redis:latest
image: redis:7.2.5
restart: unless-stopped
expose:
- 6379
Expand Down
9 changes: 8 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
# LEGACY compose path.
# Do not use this file for prod or CI/CD deployments.
# Intentional manual use requires: docker compose --profile legacy ...
version: '3.9'

services:
web:
profiles: ["legacy"]
container_name: web
build:
context: .
dockerfile: ./Dockerfile
restart: always
command: bash ./scripts/startup.sh
command: ["daphne", "-b", "0.0.0.0", "-p", "8000", "procollab.asgi:application"]
volumes:
- ./log:/procollab/log
env_file:
Expand All @@ -18,6 +22,7 @@ services:
- 8000

nginx:
profiles: ["legacy"]
container_name: nginx
build: ./nginx
depends_on:
Expand All @@ -26,6 +31,7 @@ services:
- "8000:80"

redis:
profiles: ["legacy"]
container_name: redis
image: redis:latest
expose:
Expand All @@ -34,6 +40,7 @@ services:
- redis-data:/data

celerys:
profiles: ["legacy"]
container_name: api_celery
restart: always
build:
Expand Down
7 changes: 0 additions & 7 deletions scripts/startup.sh

This file was deleted.

Loading