diff --git a/.gitea/workflows/ci-cd.yml b/.gitea/workflows/ci-cd.yml index aaf6efe..6aeeb00 100644 --- a/.gitea/workflows/ci-cd.yml +++ b/.gitea/workflows/ci-cd.yml @@ -23,6 +23,10 @@ env: REGISTRY_NAMESPACE: "${{ github.repository_owner }}" WEB_IMAGE: "mostovik-backend-web" CELERY_IMAGE: "mostovik-backend-celery" + GITEA_REGISTRY_HOST: "git.dev.nii-ecos.ru" + DOKPLOY_DEV_WEB_SERVICE_IMAGE: "service-backend-4mbxrs" + DOKPLOY_DEV_WORKER_SERVICE_IMAGE: "service-backend-512y9c" + DOKPLOY_DEV_BEAT_SERVICE_IMAGE: "service-backend-nvdyoq" CI_GOLDEN_IMAGE: "mostovik-backend-ci-golden" WEB_GOLDEN_IMAGE: "mostovik-backend-web-golden" CELERY_GOLDEN_IMAGE: "mostovik-backend-celery-golden" @@ -213,12 +217,17 @@ jobs: CELERY_REF="${REGISTRY_PATH}/${CELERY_IMAGE}" WEB_GOLDEN_REF="${REGISTRY_PATH}/${WEB_GOLDEN_IMAGE}" CELERY_GOLDEN_REF="${REGISTRY_PATH}/${CELERY_GOLDEN_IMAGE}" + DOKPLOY_REGISTRY_PATH="${GITEA_REGISTRY_HOST}/${REGISTRY_NAMESPACE}" + DOKPLOY_WEB_REF="${DOKPLOY_REGISTRY_PATH}/${DOKPLOY_DEV_WEB_SERVICE_IMAGE}" + DOKPLOY_WORKER_REF="${DOKPLOY_REGISTRY_PATH}/${DOKPLOY_DEV_WORKER_SERVICE_IMAGE}" + DOKPLOY_BEAT_REF="${DOKPLOY_REGISTRY_PATH}/${DOKPLOY_DEV_BEAT_SERVICE_IMAGE}" REGISTRY_USER="${REGISTRY_USER:-${GITHUB_ACTOR}}" REGISTRY_PASSWORD="${REGISTRY_PASSWORD:-${GITEA_TOKEN:-}}" + GITEA_REGISTRY_PASSWORD="${GITEA_TOKEN:-${REGISTRY_PASSWORD}}" unset http_proxy https_proxy HTTP_PROXY HTTPS_PROXY all_proxy ALL_PROXY - export NO_PROXY="${NO_PROXY:-},${REGISTRY_HOST}" - export no_proxy="${no_proxy:-},${REGISTRY_HOST}" + export NO_PROXY="${NO_PROXY:-},${REGISTRY_HOST},${GITEA_REGISTRY_HOST}" + export no_proxy="${no_proxy:-},${REGISTRY_HOST},${GITEA_REGISTRY_HOST}" if [ -z "${REGISTRY_PASSWORD}" ]; then echo "REGISTRY_TOKEN secret is not set and GITEA_TOKEN fallback is empty" >&2 @@ -229,14 +238,24 @@ jobs: | docker login "${REGISTRY_HOST}" \ -u "${REGISTRY_USER}" \ --password-stdin + echo "${GITEA_REGISTRY_PASSWORD}" \ + | docker login "${GITEA_REGISTRY_HOST}" \ + -u "${GITHUB_ACTOR}" \ + --password-stdin WEB_TAGS=( -t "${WEB_REF}:${BRANCH_TAG}" -t "${WEB_REF}:${BRANCH_TAG}-${SHA_SHORT}" + -t "${DOKPLOY_WEB_REF}:latest" + -t "${DOKPLOY_WEB_REF}:${BRANCH_TAG}-${SHA_SHORT}" ) CELERY_TAGS=( -t "${CELERY_REF}:${BRANCH_TAG}" -t "${CELERY_REF}:${BRANCH_TAG}-${SHA_SHORT}" + -t "${DOKPLOY_WORKER_REF}:latest" + -t "${DOKPLOY_WORKER_REF}:${BRANCH_TAG}-${SHA_SHORT}" + -t "${DOKPLOY_BEAT_REF}:latest" + -t "${DOKPLOY_BEAT_REF}:${BRANCH_TAG}-${SHA_SHORT}" ) if [ "${GITHUB_REF_NAME}" = "main" ]; then WEB_TAGS+=(-t "${WEB_REF}:latest") @@ -308,6 +327,13 @@ jobs: echo "- ${WEB_REF}:${BRANCH_TAG}-${SHA_SHORT}" echo "- ${CELERY_REF}:${BRANCH_TAG}" echo "- ${CELERY_REF}:${BRANCH_TAG}-${SHA_SHORT}" + echo "Dokploy-compatible aliases:" + echo "- ${DOKPLOY_WEB_REF}:latest" + echo "- ${DOKPLOY_WEB_REF}:${BRANCH_TAG}-${SHA_SHORT}" + echo "- ${DOKPLOY_WORKER_REF}:latest" + echo "- ${DOKPLOY_WORKER_REF}:${BRANCH_TAG}-${SHA_SHORT}" + echo "- ${DOKPLOY_BEAT_REF}:latest" + echo "- ${DOKPLOY_BEAT_REF}:${BRANCH_TAG}-${SHA_SHORT}" } >> "${GITHUB_STEP_SUMMARY:-/dev/stdout}" notify: diff --git a/scripts/ci/dokploy_deploy_image.sh b/scripts/ci/dokploy_deploy_image.sh index 407e2bb..3d0e6e7 100755 --- a/scripts/ci/dokploy_deploy_image.sh +++ b/scripts/ci/dokploy_deploy_image.sh @@ -5,13 +5,6 @@ TARGET="${1:-${DOKPLOY_TARGET:-all}}" SUMMARY_FILE="${GITHUB_STEP_SUMMARY:-/dev/stdout}" DOKPLOY_API_URL="${DOKPLOY_API_URL:-https://deploy.dev.nii-ecos.ru/api}" -require_dokploy_api_token() { - if [ -z "${DOKPLOY_API_TOKEN:-}" ]; then - echo "DOKPLOY_API_TOKEN is required to deploy prebuilt images through Dokploy API" >&2 - exit 1 - fi -} - branch_tag() { local branch branch_tag sha_short @@ -77,6 +70,130 @@ dokploy_post() { "${DOKPLOY_API_URL%/}/${endpoint}" } +legacy_webhook_url_for_target() { + case "$1" in + web) printf '%s' "${DOKPLOY_DEV_WEB_WEBHOOK_URL:-}" ;; + worker) printf '%s' "${DOKPLOY_DEV_WORKER_WEBHOOK_URL:-}" ;; + beat) printf '%s' "${DOKPLOY_DEV_BEAT_WEBHOOK_URL:-}" ;; + *) return 1 ;; + esac +} + +legacy_dokploy_payload() { + local target="$1" + + CURRENT_DOKPLOY_TARGET="${target}" python3 - <<'PY' +import json +import os + +repository = os.environ.get("GITHUB_REPOSITORY", "") +repository_name = repository.rsplit("/", 1)[-1] +branch = os.environ.get("GITHUB_REF_NAME") or "dev" +sha = os.environ.get("GITHUB_SHA") or "" +server_url = os.environ.get("GITHUB_SERVER_URL", "").rstrip("/") +repository_url = f"{server_url}/{repository}" if server_url and repository else "" +image_tag = f"{branch.replace('/', '-')}-{sha[:7]}" if branch and sha else branch or "dev" +celery_image = ( + f"{os.environ['REGISTRY_HOST']}/{os.environ['REGISTRY_NAMESPACE']}/" + f"{os.environ['CELERY_IMAGE']}:{image_tag}" +) +payload = { + "ref": f"refs/heads/{branch}", + "after": sha, + "checkout_sha": sha, + "repository": { + "name": repository_name, + "full_name": repository, + "html_url": repository_url, + "clone_url": f"{repository_url}.git" if repository_url else "", + }, + "sender": {"login": os.environ.get("GITHUB_ACTOR")}, + "pusher": {"name": os.environ.get("GITHUB_ACTOR")}, + "head_commit": { + "id": sha, + "message": f"CI deploy {os.environ.get('CURRENT_DOKPLOY_TARGET')}", + "url": f"{repository_url}/commit/{sha}" if repository_url and sha else "", + }, + "commits": [ + { + "id": sha, + "message": f"CI deploy {os.environ.get('CURRENT_DOKPLOY_TARGET')}", + "url": f"{repository_url}/commit/{sha}" if repository_url and sha else "", + } + ], + "project": repository, + "branch": branch, + "sha": sha, + "actor": os.environ.get("GITHUB_ACTOR"), + "target": os.environ.get("CURRENT_DOKPLOY_TARGET"), + "image_tag": image_tag, + "images": { + "web": ( + f"{os.environ['REGISTRY_HOST']}/{os.environ['REGISTRY_NAMESPACE']}/" + f"{os.environ['WEB_IMAGE']}:{image_tag}" + ), + "worker": celery_image, + "beat": celery_image, + }, +} +print(json.dumps(payload, ensure_ascii=True, separators=(",", ":"))) +PY +} + +legacy_webhook_deploy_target() { + local target="$1" + local webhook_url payload response + + webhook_url="$(legacy_webhook_url_for_target "${target}")" + if [ -z "${webhook_url}" ]; then + echo "DOKPLOY_API_TOKEN is not set and legacy webhook URL for ${target} is missing" >&2 + exit 1 + fi + + payload="$(legacy_dokploy_payload "${target}")" + echo "Dokploy ${target}: fallback to legacy deploy webhook" + response="$(curl -fsS \ + --connect-timeout 5 \ + --max-time 30 \ + --retry 2 \ + --retry-delay 2 \ + -X POST \ + -H "Content-Type: application/json" \ + -H "X-Gitea-Event: push" \ + -H "X-Gogs-Event: push" \ + -H "X-GitHub-Event: push" \ + --data "${payload}" \ + "${webhook_url}")" + printf '%s\n' "${response}" + + if printf '%s' "${response}" | grep -qi "Branch Not Match"; then + echo "Dokploy rejected ${target}: branch did not match" >&2 + exit 1 + fi + + { + echo "- ${target}: legacy webhook fallback" + } >>"${SUMMARY_FILE}" +} + +legacy_webhook_deploy() { + { + echo "Dokploy Docker-image deploy:" + echo "DOKPLOY_API_TOKEN is not set; falling back to legacy webhooks." + echo "Build job still pushes Dokploy-compatible git.dev image aliases." + } >>"${SUMMARY_FILE}" + + if [ "${TARGET}" = "all" ] || [ "${TARGET}" = "web" ]; then + legacy_webhook_deploy_target "web" + fi + if [ "${TARGET}" = "all" ] || [ "${TARGET}" = "worker" ] || [ "${TARGET}" = "celery" ]; then + legacy_webhook_deploy_target "worker" + fi + if [ "${TARGET}" = "all" ] || [ "${TARGET}" = "beat" ]; then + legacy_webhook_deploy_target "beat" + fi +} + resolve_application_id() { local explicit_id="$1" local app_name="$2" @@ -246,9 +363,6 @@ deploy_target() { } main() { - require_dokploy_api_token - require_registry_credentials - case "${TARGET}" in all | web | worker | celery | beat) ;; *) @@ -257,6 +371,13 @@ main() { ;; esac + if [ -z "${DOKPLOY_API_TOKEN:-}" ]; then + legacy_webhook_deploy + return 0 + fi + + require_registry_credentials + { echo "Dokploy Docker-image deploy:" echo "Registry API: ${REGISTRY_API_URL:-${REGISTRY_HOST}}" diff --git a/scripts/ci/manual_dev_action.sh b/scripts/ci/manual_dev_action.sh index ca9ee4f..ebe33ba 100755 --- a/scripts/ci/manual_dev_action.sh +++ b/scripts/ci/manual_dev_action.sh @@ -100,13 +100,6 @@ build_golden_images() { } >>"${SUMMARY_FILE}" } -require_dokploy_api_token() { - if [ -z "${DOKPLOY_API_TOKEN:-}" ]; then - echo "DOKPLOY_API_TOKEN is required for Dokploy image deploy" >&2 - exit 1 - fi -} - trigger_dokploy() { local target="$1" case "${target}" in @@ -252,7 +245,6 @@ cleanup_dev_database() { exit 1 fi - require_dokploy_api_token install_postgres_client drop_and_recreate_database bash scripts/ci/dokploy_deploy_image.sh web