ci: wire dokploy deploy triggers #no_deploy
All checks were successful
CI/CD Pipeline / Manual Action Help (push) Has been skipped
CI/CD Pipeline / Start Dev Containers in Dokploy (push) Has been skipped
CI/CD Pipeline / Cleanup Dev Database (push) Has been skipped
CI/CD Pipeline / Quality Gate (push) Successful in 1m47s
CI/CD Pipeline / Build and Push Images (push) Successful in 2m49s
CI/CD Pipeline / Deploy Dev in Dokploy (push) Has been skipped
CI/CD Pipeline / Internal Notify (push) Successful in 1s

This commit is contained in:
2026-04-28 13:18:06 +02:00
parent 6a9e96922c
commit 4aa552341f
3 changed files with 207 additions and 39 deletions

View File

@@ -18,11 +18,11 @@ on:
required: true
default: "noop"
dokploy_target:
description: "Dokploy dev target: all, web, or celery"
description: "Dokploy dev target: all, web, worker, or beat"
required: true
default: "all"
cleanup_confirm:
description: "Type CLEAN_DEV_DB to drop and recreate the dev public schema"
description: "Type CLEAN_DEV_DB to recreate/reset the dev database as UTF8"
required: false
default: ""
@@ -37,6 +37,9 @@ env:
REGISTRY_NAMESPACE: "${{ github.repository_owner }}"
WEB_IMAGE: "mostovik-backend-web"
CELERY_IMAGE: "mostovik-backend-celery"
DOKPLOY_DEV_WEB_WEBHOOK_URL: "https://deploy.dev.nii-ecos.ru/api/deploy/_EjfuYBpzGJ18uPwBZ3iF"
DOKPLOY_DEV_WORKER_WEBHOOK_URL: "https://deploy.dev.nii-ecos.ru/api/deploy/hltL7K2HmG1a8EIzr-mVA"
DOKPLOY_DEV_BEAT_WEBHOOK_URL: "https://deploy.dev.nii-ecos.ru/api/deploy/RkdykbqU6faErrZBAN9Rv"
UV_VERSION: "0.7.2"
PIP_DISABLE_PIP_VERSION_CHECK: "1"
@@ -59,7 +62,7 @@ jobs:
echo "For dev DB cleanup run with:"
echo "- manual_action=cleanup_dev_database"
echo "- cleanup_confirm=CLEAN_DEV_DB"
echo "For Dokploy start run with manual_action=dokploy_start."
echo "For Dokploy start run with manual_action=dokploy_start and dokploy_target=all|web|worker|beat."
} >> "${GITHUB_STEP_SUMMARY:-/dev/stdout}"
quality:
@@ -308,6 +311,79 @@ jobs:
--data "${PAYLOAD}" \
"${CI_NOTIFY_WEBHOOK_URL}"
deploy_dev:
name: Deploy Dev in Dokploy
runs-on: ubuntu-latest
timeout-minutes: 5
needs: [build_push]
if: |
github.event_name == 'push' &&
github.ref == 'refs/heads/dev' &&
needs.build_push.result == 'success' &&
!contains(github.event.head_commit.message, '#no_deploy')
steps:
- name: Trigger dev Dokploy webhooks
env:
DOKPLOY_API_TOKEN: ${{ secrets.DOKPLOY_API_TOKEN }}
run: |
set -euo pipefail
call_webhook() {
service_name="$1"
webhook_url="$2"
target="$3"
AUTH_HEADER=()
if [ -n "${DOKPLOY_API_TOKEN:-}" ]; then
AUTH_HEADER=(-H "Authorization: Bearer ${DOKPLOY_API_TOKEN}")
fi
PAYLOAD=$(CURRENT_DOKPLOY_TARGET="${target}" python3 - <<'PY'
import json
import os
celery_image = f"{os.environ['REGISTRY_HOST']}/{os.environ['REGISTRY_NAMESPACE']}/{os.environ['CELERY_IMAGE']}:dev"
payload = {
"project": os.environ.get("GITHUB_REPOSITORY"),
"branch": os.environ.get("GITHUB_REF_NAME"),
"sha": os.environ.get("GITHUB_SHA"),
"actor": os.environ.get("GITHUB_ACTOR"),
"target": os.environ.get("CURRENT_DOKPLOY_TARGET"),
"images": {
"web": f"{os.environ['REGISTRY_HOST']}/{os.environ['REGISTRY_NAMESPACE']}/{os.environ['WEB_IMAGE']}:dev",
"worker": celery_image,
"beat": celery_image,
},
}
print(json.dumps(payload, ensure_ascii=True, separators=(",", ":")))
PY
)
echo "Trigger Dokploy for ${service_name}"
curl -fsS \
--connect-timeout 5 \
--max-time 30 \
--retry 2 \
--retry-delay 2 \
-X POST \
-H "Content-Type: application/json" \
"${AUTH_HEADER[@]}" \
--data "${PAYLOAD}" \
"${webhook_url}"
}
call_webhook "dev web" "${DOKPLOY_DEV_WEB_WEBHOOK_URL}" "web"
call_webhook "dev worker" "${DOKPLOY_DEV_WORKER_WEBHOOK_URL}" "worker"
call_webhook "dev beat" "${DOKPLOY_DEV_BEAT_WEBHOOK_URL}" "beat"
{
echo "Dokploy dev deploy triggered."
echo "Web image: ${REGISTRY_HOST}/${REGISTRY_NAMESPACE}/${WEB_IMAGE}:dev"
echo "Worker image: ${REGISTRY_HOST}/${REGISTRY_NAMESPACE}/${CELERY_IMAGE}:dev"
echo "Beat image: ${REGISTRY_HOST}/${REGISTRY_NAMESPACE}/${CELERY_IMAGE}:dev"
} >> "${GITHUB_STEP_SUMMARY:-/dev/stdout}"
dokploy_dev_start:
name: Start Dev Containers in Dokploy
runs-on: ubuntu-latest
@@ -321,18 +397,15 @@ jobs:
- name: Trigger Dokploy webhooks
env:
DOKPLOY_TARGET: ${{ github.event.inputs.dokploy_target }}
DOKPLOY_DEV_WEBHOOK_URL: ${{ secrets.DOKPLOY_DEV_WEBHOOK_URL }}
DOKPLOY_DEV_WEB_WEBHOOK_URL: ${{ secrets.DOKPLOY_DEV_WEB_WEBHOOK_URL }}
DOKPLOY_DEV_CELERY_WEBHOOK_URL: ${{ secrets.DOKPLOY_DEV_CELERY_WEBHOOK_URL }}
DOKPLOY_API_TOKEN: ${{ secrets.DOKPLOY_API_TOKEN }}
run: |
set -euo pipefail
TARGET="${DOKPLOY_TARGET:-all}"
case "${TARGET}" in
all|web|celery) ;;
all|web|worker|celery|beat) ;;
*)
echo "dokploy_target must be one of: all, web, celery" >&2
echo "dokploy_target must be one of: all, web, worker, beat" >&2
exit 1
;;
esac
@@ -340,6 +413,7 @@ jobs:
call_webhook() {
service_name="$1"
webhook_url="$2"
target="$3"
if [ -z "${webhook_url}" ]; then
echo "Dokploy webhook for ${service_name} is not configured" >&2
@@ -351,10 +425,11 @@ jobs:
AUTH_HEADER=(-H "Authorization: Bearer ${DOKPLOY_API_TOKEN}")
fi
PAYLOAD=$(python3 - <<'PY'
PAYLOAD=$(CURRENT_DOKPLOY_TARGET="${target}" python3 - <<'PY'
import json
import os
celery_image = f"{os.environ['REGISTRY_HOST']}/{os.environ['REGISTRY_NAMESPACE']}/{os.environ['CELERY_IMAGE']}:dev"
payload = {
"project": os.environ.get("GITHUB_REPOSITORY"),
"branch": os.environ.get("GITHUB_REF_NAME"),
@@ -362,8 +437,9 @@ jobs:
"actor": os.environ.get("GITHUB_ACTOR"),
"target": os.environ.get("CURRENT_DOKPLOY_TARGET"),
"images": {
"web": "registry.dev.nii-ecos.ru/avm/mostovik-backend-web:dev",
"celery": "registry.dev.nii-ecos.ru/avm/mostovik-backend-celery:dev",
"web": f"{os.environ['REGISTRY_HOST']}/{os.environ['REGISTRY_NAMESPACE']}/{os.environ['WEB_IMAGE']}:dev",
"worker": celery_image,
"beat": celery_image,
},
}
print(json.dumps(payload, ensure_ascii=True, separators=(",", ":")))
@@ -385,19 +461,19 @@ jobs:
triggered=0
if [ "${TARGET}" = "all" ] && [ -n "${DOKPLOY_DEV_WEBHOOK_URL:-}" ]; then
CURRENT_DOKPLOY_TARGET="all" call_webhook "dev stack" "${DOKPLOY_DEV_WEBHOOK_URL}"
if [ "${TARGET}" = "all" ] || [ "${TARGET}" = "web" ]; then
call_webhook "dev web" "${DOKPLOY_DEV_WEB_WEBHOOK_URL}" "web"
triggered=1
else
if [ "${TARGET}" = "all" ] || [ "${TARGET}" = "web" ]; then
CURRENT_DOKPLOY_TARGET="web" call_webhook "dev web" "${DOKPLOY_DEV_WEB_WEBHOOK_URL:-${DOKPLOY_DEV_WEBHOOK_URL:-}}"
triggered=1
fi
fi
if [ "${TARGET}" = "all" ] || [ "${TARGET}" = "celery" ]; then
CURRENT_DOKPLOY_TARGET="celery" call_webhook "dev celery" "${DOKPLOY_DEV_CELERY_WEBHOOK_URL:-${DOKPLOY_DEV_WEBHOOK_URL:-}}"
triggered=1
fi
if [ "${TARGET}" = "all" ] || [ "${TARGET}" = "worker" ] || [ "${TARGET}" = "celery" ]; then
call_webhook "dev worker" "${DOKPLOY_DEV_WORKER_WEBHOOK_URL}" "worker"
triggered=1
fi
if [ "${TARGET}" = "all" ] || [ "${TARGET}" = "beat" ]; then
call_webhook "dev beat" "${DOKPLOY_DEV_BEAT_WEBHOOK_URL}" "beat"
triggered=1
fi
if [ "${triggered}" -ne 1 ]; then
@@ -409,8 +485,9 @@ jobs:
echo "Dokploy dev trigger completed."
echo "Target: ${TARGET}"
echo "Registry API: ${REGISTRY_API_URL}"
echo "Web image: registry.dev.nii-ecos.ru/avm/mostovik-backend-web:dev"
echo "Celery image: registry.dev.nii-ecos.ru/avm/mostovik-backend-celery:dev"
echo "Web image: ${REGISTRY_HOST}/${REGISTRY_NAMESPACE}/${WEB_IMAGE}:dev"
echo "Worker image: ${REGISTRY_HOST}/${REGISTRY_NAMESPACE}/${CELERY_IMAGE}:dev"
echo "Beat image: ${REGISTRY_HOST}/${REGISTRY_NAMESPACE}/${CELERY_IMAGE}:dev"
} >> "${GITHUB_STEP_SUMMARY:-/dev/stdout}"
cleanup_dev_database:
@@ -451,28 +528,87 @@ jobs:
"${APT_RUNNER[@]}" apt-get update
"${APT_RUNNER[@]}" apt-get install -y postgresql-client
- name: Drop and recreate public schema
- name: Recreate UTF8 database or reset public schema
run: |
set -euo pipefail
export PGPASSWORD="${POSTGRES_PASSWORD}"
terminate_connections() {
psql \
--set ON_ERROR_STOP=1 \
--host="${POSTGRES_HOST}" \
--port="${POSTGRES_PORT}" \
--username="${POSTGRES_USER}" \
--dbname=postgres \
--set=dbname="${POSTGRES_DB}" \
<<'SQL'
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE datname = :'dbname'
AND pid <> pg_backend_pid();
SQL
}
ENCODING=$(psql \
--set ON_ERROR_STOP=1 \
--host="${POSTGRES_HOST}" \
--port="${POSTGRES_PORT}" \
--username="${POSTGRES_USER}" \
--dbname=postgres \
--tuples-only \
--no-align \
--set=dbname="${POSTGRES_DB}" \
--command="SELECT pg_encoding_to_char(encoding) FROM pg_database WHERE datname = :'dbname';")
if [ "${ENCODING:-}" != "UTF8" ]; then
echo "Database ${POSTGRES_DB} encoding is ${ENCODING:-missing}; recreating as UTF8"
terminate_connections
psql \
--set ON_ERROR_STOP=1 \
--host="${POSTGRES_HOST}" \
--port="${POSTGRES_PORT}" \
--username="${POSTGRES_USER}" \
--dbname=postgres \
--set=dbname="${POSTGRES_DB}" \
--set=dbuser="${POSTGRES_USER}" \
<<'SQL'
DROP DATABASE IF EXISTS :"dbname";
CREATE DATABASE :"dbname" WITH OWNER :"dbuser" TEMPLATE template0 ENCODING 'UTF8';
SQL
else
echo "Database ${POSTGRES_DB} is already UTF8; resetting public schema"
terminate_connections
psql \
--set ON_ERROR_STOP=1 \
--host="${POSTGRES_HOST}" \
--port="${POSTGRES_PORT}" \
--username="${POSTGRES_USER}" \
--dbname="${POSTGRES_DB}" \
--set=dbuser="${POSTGRES_USER}" \
<<'SQL'
DROP SCHEMA IF EXISTS public CASCADE;
CREATE SCHEMA public AUTHORIZATION :"dbuser";
GRANT ALL ON SCHEMA public TO :"dbuser";
GRANT ALL ON SCHEMA public TO public;
SQL
fi
psql \
--set ON_ERROR_STOP=1 \
--host="${POSTGRES_HOST}" \
--port="${POSTGRES_PORT}" \
--username="${POSTGRES_USER}" \
--dbname="${POSTGRES_DB}" \
<<'SQL'
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE datname = current_database()
AND pid <> pg_backend_pid();
--dbname=postgres \
--tuples-only \
--no-align \
--set=dbname="${POSTGRES_DB}" \
--command="SELECT pg_encoding_to_char(encoding) FROM pg_database WHERE datname = :'dbname';" \
| tee /tmp/mostovik-db-encoding
DROP SCHEMA IF EXISTS public CASCADE;
CREATE SCHEMA public;
GRANT ALL ON SCHEMA public TO postgres;
GRANT ALL ON SCHEMA public TO public;
SQL
if [ "$(cat /tmp/mostovik-db-encoding)" != "UTF8" ]; then
echo "Database ${POSTGRES_DB} is not UTF8 after cleanup" >&2
exit 1
fi
- name: Summary
run: |
@@ -480,4 +616,5 @@ jobs:
{
echo "Dev database cleanup completed."
echo "Database: ${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}"
echo "Encoding: UTF8"
} >> "${GITHUB_STEP_SUMMARY:-/dev/stdout}"