ci: streamline pipeline and add dev deploy actions
Some checks failed
CI/CD Pipeline / Start Dev Containers in Dokploy (push) Has been skipped
CI/CD Pipeline / Start Dev Containers in Dokploy (pull_request) Has been skipped
CI/CD Pipeline / Quality Gate (pull_request) Failing after 2m47s
CI/CD Pipeline / Build and Push Images (pull_request) Has been skipped
CI/CD Pipeline / Quality Gate (push) Successful in 3m14s
CI/CD Pipeline / Build and Push Images (push) Has been skipped
CI/CD Pipeline / Internal Notify (pull_request) Successful in 1s
CI/CD Pipeline / Internal Notify (push) Successful in 1s
Some checks failed
CI/CD Pipeline / Start Dev Containers in Dokploy (push) Has been skipped
CI/CD Pipeline / Start Dev Containers in Dokploy (pull_request) Has been skipped
CI/CD Pipeline / Quality Gate (pull_request) Failing after 2m47s
CI/CD Pipeline / Build and Push Images (pull_request) Has been skipped
CI/CD Pipeline / Quality Gate (push) Successful in 3m14s
CI/CD Pipeline / Build and Push Images (push) Has been skipped
CI/CD Pipeline / Internal Notify (pull_request) Successful in 1s
CI/CD Pipeline / Internal Notify (push) Successful in 1s
This commit is contained in:
@@ -5,27 +5,44 @@ on:
|
||||
branches:
|
||||
- main
|
||||
- dev
|
||||
- "feature/**"
|
||||
- "codex/**"
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
- dev
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
dokploy_target:
|
||||
description: "Dokploy dev target: all, web, or celery"
|
||||
required: true
|
||||
default: "all"
|
||||
|
||||
concurrency:
|
||||
group: mostovik-backend-${{ github.workflow }}-${{ github.event_name }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
PYTHON_VERSION: "3.11"
|
||||
REGISTRY_HOST: "10.10.0.50"
|
||||
REGISTRY_NAMESPACE: "${{ github.repository_owner }}"
|
||||
WEB_IMAGE: "mostovik-backend-web"
|
||||
CELERY_IMAGE: "mostovik-backend-celery"
|
||||
CRANE_VERSION: "v0.19.0"
|
||||
UV_VERSION: "0.7.2"
|
||||
PIP_DISABLE_PIP_VERSION_CHECK: "1"
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
name: Code Quality Checks
|
||||
quality:
|
||||
name: Quality Gate
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
if: ${{ !contains(github.event.head_commit.message, '#no_lint') }}
|
||||
env:
|
||||
TG_BOT_KEY: ${{ secrets.TG_BOT_KEY }}
|
||||
TG_CHANNEL: ${{ secrets.TG_CHANNEL }}
|
||||
timeout-minutes: 25
|
||||
if: ${{ github.event_name != 'workflow_dispatch' }}
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
run: |
|
||||
set -euo pipefail
|
||||
REPO_URL=$(echo "${GITHUB_SERVER_URL}" | sed "s|://|://oauth2:${{ gitea.token }}@|")
|
||||
BRANCH="${GITHUB_HEAD_REF:-${GITHUB_REF_NAME}}"
|
||||
git clone --depth=1 --branch="${BRANCH}" "${REPO_URL}/${GITHUB_REPOSITORY}.git" .
|
||||
@@ -45,7 +62,7 @@ jobs:
|
||||
. ./.ci-python-env
|
||||
"${PYTHON_BIN}" -m venv .venv
|
||||
. .venv/bin/activate
|
||||
python -m pip install --upgrade pip uv
|
||||
python -m pip install "uv==${UV_VERSION}"
|
||||
uv sync \
|
||||
--dev \
|
||||
--frozen \
|
||||
@@ -55,87 +72,21 @@ jobs:
|
||||
--no-python-downloads
|
||||
|
||||
- name: Run Ruff linting
|
||||
if: ${{ !contains(github.event.head_commit.message, '#no_lint') }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
. .venv/bin/activate
|
||||
ruff check src
|
||||
|
||||
- name: Run Ruff formatting check
|
||||
if: ${{ !contains(github.event.head_commit.message, '#no_lint') }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
. .venv/bin/activate
|
||||
ruff format src --check
|
||||
|
||||
- name: Telegram notify (lint failed)
|
||||
if: failure()
|
||||
continue-on-error: true
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [ -z "${TG_BOT_KEY:-}" ] || [ -z "${TG_CHANNEL:-}" ]; then
|
||||
echo "TG_BOT_KEY or TG_CHANNEL is not set; skip telegram notification"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
COMMIT_MESSAGE=$(git log -1 --pretty=%s 2>/dev/null || echo "n/a")
|
||||
|
||||
MSG="❌ [mostovik-backend] lint failed
|
||||
branch=${GITHUB_REF_NAME}
|
||||
sha=${GITHUB_SHA}
|
||||
actor=${GITHUB_ACTOR}
|
||||
commit=${COMMIT_MESSAGE}"
|
||||
|
||||
curl -fsS \
|
||||
--connect-timeout 5 \
|
||||
--max-time 15 \
|
||||
--retry 2 \
|
||||
--retry-delay 2 \
|
||||
--retry-all-errors \
|
||||
-X POST "https://api.telegram.org/bot${TG_BOT_KEY}/sendMessage" \
|
||||
-d "chat_id=${TG_CHANNEL}" \
|
||||
--data-urlencode "text=${MSG}" \
|
||||
|| echo "Telegram notification failed; continue pipeline"
|
||||
|
||||
test:
|
||||
name: Run Tests
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 20
|
||||
if: ${{ !contains(github.event.head_commit.message, '#no_test') }}
|
||||
env:
|
||||
TG_BOT_KEY: ${{ secrets.TG_BOT_KEY }}
|
||||
TG_CHANNEL: ${{ secrets.TG_CHANNEL }}
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
run: |
|
||||
REPO_URL=$(echo "${GITHUB_SERVER_URL}" | sed "s|://|://oauth2:${{ gitea.token }}@|")
|
||||
BRANCH="${GITHUB_HEAD_REF:-${GITHUB_REF_NAME}}"
|
||||
git clone --depth=1 --branch="${BRANCH}" "${REPO_URL}/${GITHUB_REPOSITORY}.git" .
|
||||
git checkout "${GITHUB_SHA}"
|
||||
|
||||
- name: Install Python and uv
|
||||
run: |
|
||||
set -euo pipefail
|
||||
PROJECT_PYTHON_VERSION="$(cat .python-version 2>/dev/null || printf '%s' "${PYTHON_VERSION}")"
|
||||
PYTHON_BIN="$(./scripts/ensure-ci-python.sh "${PROJECT_PYTHON_VERSION}")"
|
||||
|
||||
printf 'PYTHON_BIN=%s\n' "${PYTHON_BIN}" > .ci-python-env
|
||||
|
||||
- name: Create virtual environment and install dependencies
|
||||
run: |
|
||||
set -euo pipefail
|
||||
. ./.ci-python-env
|
||||
"${PYTHON_BIN}" -m venv .venv
|
||||
. .venv/bin/activate
|
||||
python -m pip install --upgrade pip uv
|
||||
uv sync \
|
||||
--dev \
|
||||
--frozen \
|
||||
--active \
|
||||
--python "${PYTHON_BIN}" \
|
||||
--no-managed-python \
|
||||
--no-python-downloads
|
||||
|
||||
- name: Run regular pytest suite
|
||||
if: ${{ !contains(github.event.head_commit.message, '#no_test') }}
|
||||
env:
|
||||
DJANGO_SETTINGS_MODULE: settings.test
|
||||
SECRET_KEY: test-secret-key-for-ci
|
||||
@@ -144,90 +95,8 @@ jobs:
|
||||
export PYTHONPATH="${PWD}/src:${PYTHONPATH:-}"
|
||||
.venv/bin/python -m pytest tests --ignore=tests/test_api_inventory_e2e.py -q
|
||||
|
||||
- name: Pack prepared test workspace
|
||||
if: success()
|
||||
run: |
|
||||
set -euo pipefail
|
||||
WORKSPACE_ARCHIVE="/tmp/ci-test-workspace.tar.gz"
|
||||
tar \
|
||||
--exclude='.git' \
|
||||
--exclude='.pytest_cache' \
|
||||
--exclude='htmlcov' \
|
||||
--exclude='__pycache__' \
|
||||
-czf "${WORKSPACE_ARCHIVE}" \
|
||||
.
|
||||
|
||||
- name: Upload prepared test workspace
|
||||
if: success()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ci-test-workspace
|
||||
path: /tmp/ci-test-workspace.tar.gz
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
- name: Telegram notify (test failed)
|
||||
if: failure()
|
||||
continue-on-error: true
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [ -z "${TG_BOT_KEY:-}" ] || [ -z "${TG_CHANNEL:-}" ]; then
|
||||
echo "TG_BOT_KEY or TG_CHANNEL is not set; skip telegram notification"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
COMMIT_MESSAGE=$(git log -1 --pretty=%s 2>/dev/null || echo "n/a")
|
||||
|
||||
MSG="❌ [mostovik-backend] test failed
|
||||
branch=${GITHUB_REF_NAME}
|
||||
sha=${GITHUB_SHA}
|
||||
actor=${GITHUB_ACTOR}
|
||||
commit=${COMMIT_MESSAGE}"
|
||||
|
||||
curl -fsS \
|
||||
--connect-timeout 5 \
|
||||
--max-time 15 \
|
||||
--retry 2 \
|
||||
--retry-delay 2 \
|
||||
--retry-all-errors \
|
||||
-X POST "https://api.telegram.org/bot${TG_BOT_KEY}/sendMessage" \
|
||||
-d "chat_id=${TG_CHANNEL}" \
|
||||
--data-urlencode "text=${MSG}" \
|
||||
|| echo "Telegram notification failed; continue pipeline"
|
||||
|
||||
test_api_inventory_e2e:
|
||||
name: Run API Inventory E2E Tests
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
needs: [test]
|
||||
if: ${{ needs.test.result == 'success' }}
|
||||
env:
|
||||
TG_BOT_KEY: ${{ secrets.TG_BOT_KEY }}
|
||||
TG_CHANNEL: ${{ secrets.TG_CHANNEL }}
|
||||
|
||||
steps:
|
||||
- name: Download prepared test workspace
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: ci-test-workspace
|
||||
|
||||
- name: Extract prepared test workspace
|
||||
run: |
|
||||
set -euo pipefail
|
||||
ARCHIVE_PATH="$(find . -maxdepth 2 -name 'ci-test-workspace.tar.gz' -print -quit)"
|
||||
if [ -z "${ARCHIVE_PATH}" ]; then
|
||||
echo "ci-test-workspace.tar.gz not found after artifact download" >&2
|
||||
exit 1
|
||||
fi
|
||||
tar -xzf "${ARCHIVE_PATH}"
|
||||
|
||||
- name: Install Python for artifact environment
|
||||
run: |
|
||||
set -euo pipefail
|
||||
PROJECT_PYTHON_VERSION="$(cat .python-version 2>/dev/null || printf '%s' "${PYTHON_VERSION}")"
|
||||
./scripts/ensure-ci-python.sh "${PROJECT_PYTHON_VERSION}" >/dev/null
|
||||
|
||||
- name: Run API inventory pytest suite
|
||||
if: ${{ !contains(github.event.head_commit.message, '#no_test') }}
|
||||
env:
|
||||
DJANGO_SETTINGS_MODULE: settings.test
|
||||
SECRET_KEY: test-secret-key-for-ci
|
||||
@@ -236,70 +105,268 @@ jobs:
|
||||
export PYTHONPATH="${PWD}/src:${PYTHONPATH:-}"
|
||||
.venv/bin/python -m pytest tests/test_api_inventory_e2e.py -q
|
||||
|
||||
- name: Telegram notify (api inventory e2e failed)
|
||||
if: failure()
|
||||
continue-on-error: true
|
||||
build_push:
|
||||
name: Build and Push Images
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 45
|
||||
needs: [quality]
|
||||
if: |
|
||||
github.event_name == 'push' &&
|
||||
(github.ref == 'refs/heads/dev' || github.ref == 'refs/heads/main') &&
|
||||
needs.quality.result == 'success' &&
|
||||
!contains(github.event.head_commit.message, '#no_image')
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [ -z "${TG_BOT_KEY:-}" ] || [ -z "${TG_CHANNEL:-}" ]; then
|
||||
echo "TG_BOT_KEY or TG_CHANNEL is not set; skip telegram notification"
|
||||
exit 0
|
||||
REPO_URL=$(echo "${GITHUB_SERVER_URL}" | sed "s|://|://oauth2:${{ gitea.token }}@|")
|
||||
BRANCH="${GITHUB_HEAD_REF:-${GITHUB_REF_NAME}}"
|
||||
git clone --depth=1 --branch="${BRANCH}" "${REPO_URL}/${GITHUB_REPOSITORY}.git" .
|
||||
git checkout "${GITHUB_SHA}"
|
||||
|
||||
- name: Build and push branch images
|
||||
env:
|
||||
GITEA_TOKEN: ${{ gitea.token }}
|
||||
REGISTRY_USER: ${{ secrets.REGISTRY_USER }}
|
||||
REGISTRY_PASSWORD: ${{ secrets.REGISTRY_TOKEN }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
curl -fsSL \
|
||||
"https://github.com/google/go-containerregistry/releases/download/${CRANE_VERSION}/go-containerregistry_Linux_x86_64.tar.gz" \
|
||||
| tar xz crane
|
||||
chmod +x crane
|
||||
|
||||
BRANCH="${GITHUB_HEAD_REF:-${GITHUB_REF_NAME:-branch}}"
|
||||
BRANCH_TAG=$(printf '%s' "${BRANCH}" \
|
||||
| tr '[:upper:]' '[:lower:]' \
|
||||
| sed -E 's#[/[:space:]]+#-#g; s#[^a-z0-9_.-]+#-#g; s#^-+##; s#-+$##')
|
||||
BRANCH_TAG="${BRANCH_TAG:-branch}"
|
||||
BRANCH_TAG=$(printf '%.120s' "${BRANCH_TAG}")
|
||||
SHA_SHORT=$(printf '%s' "${GITHUB_SHA}" | cut -c1-7)
|
||||
|
||||
REGISTRY_PATH="${REGISTRY_HOST}/${REGISTRY_NAMESPACE}"
|
||||
WEB_REF="${REGISTRY_PATH}/${WEB_IMAGE}"
|
||||
CELERY_REF="${REGISTRY_PATH}/${CELERY_IMAGE}"
|
||||
REGISTRY_USER="${REGISTRY_USER:-${GITHUB_ACTOR}}"
|
||||
REGISTRY_PASSWORD="${REGISTRY_PASSWORD:-${GITEA_TOKEN:-}}"
|
||||
|
||||
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}"
|
||||
|
||||
if [ -z "${REGISTRY_PASSWORD}" ]; then
|
||||
echo "REGISTRY_TOKEN secret is not set and gitea.token fallback is empty" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
MSG="❌ [mostovik-backend] api inventory e2e failed
|
||||
branch=${GITHUB_REF_NAME}
|
||||
sha=${GITHUB_SHA}
|
||||
actor=${GITHUB_ACTOR}"
|
||||
echo "${REGISTRY_PASSWORD}" \
|
||||
| ./crane auth login --insecure "${REGISTRY_HOST}" \
|
||||
-u "${REGISTRY_USER}" \
|
||||
--password-stdin
|
||||
|
||||
curl -fsS \
|
||||
--connect-timeout 5 \
|
||||
--max-time 15 \
|
||||
--retry 2 \
|
||||
--retry-delay 2 \
|
||||
--retry-all-errors \
|
||||
-X POST "https://api.telegram.org/bot${TG_BOT_KEY}/sendMessage" \
|
||||
-d "chat_id=${TG_CHANNEL}" \
|
||||
--data-urlencode "text=${MSG}" \
|
||||
|| echo "Telegram notification failed; continue pipeline"
|
||||
docker build \
|
||||
-f ./docker/Dockerfile \
|
||||
--target runtime-web \
|
||||
--build-arg INSTALL_DEV=false \
|
||||
--label "org.opencontainers.image.revision=${GITHUB_SHA}" \
|
||||
--label "org.opencontainers.image.source=${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}" \
|
||||
-t "${WEB_IMAGE}:local" .
|
||||
docker save "${WEB_IMAGE}:local" -o /tmp/web.tar
|
||||
|
||||
notify_success:
|
||||
name: Telegram Notify Success
|
||||
./crane push --insecure /tmp/web.tar "${WEB_REF}:${BRANCH_TAG}"
|
||||
./crane push --insecure /tmp/web.tar "${WEB_REF}:${BRANCH_TAG}-${SHA_SHORT}"
|
||||
if [ "${GITHUB_REF_NAME}" = "main" ]; then
|
||||
./crane push --insecure /tmp/web.tar "${WEB_REF}:latest"
|
||||
fi
|
||||
|
||||
docker build \
|
||||
-f ./docker/Dockerfile \
|
||||
--target runtime-celery \
|
||||
--build-arg INSTALL_DEV=false \
|
||||
--label "org.opencontainers.image.revision=${GITHUB_SHA}" \
|
||||
--label "org.opencontainers.image.source=${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}" \
|
||||
-t "${CELERY_IMAGE}:local" .
|
||||
docker save "${CELERY_IMAGE}:local" -o /tmp/celery.tar
|
||||
|
||||
./crane push --insecure /tmp/celery.tar "${CELERY_REF}:${BRANCH_TAG}"
|
||||
./crane push --insecure /tmp/celery.tar "${CELERY_REF}:${BRANCH_TAG}-${SHA_SHORT}"
|
||||
if [ "${GITHUB_REF_NAME}" = "main" ]; then
|
||||
./crane push --insecure /tmp/celery.tar "${CELERY_REF}:latest"
|
||||
fi
|
||||
|
||||
{
|
||||
echo "Pushed images:"
|
||||
echo "- ${WEB_REF}:${BRANCH_TAG}"
|
||||
echo "- ${WEB_REF}:${BRANCH_TAG}-${SHA_SHORT}"
|
||||
echo "- ${CELERY_REF}:${BRANCH_TAG}"
|
||||
echo "- ${CELERY_REF}:${BRANCH_TAG}-${SHA_SHORT}"
|
||||
} >> "${GITHUB_STEP_SUMMARY:-/dev/stdout}"
|
||||
|
||||
notify:
|
||||
name: Internal Notify
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 1
|
||||
needs: [lint, test, test_api_inventory_e2e]
|
||||
if: |
|
||||
always() &&
|
||||
needs.lint.result == 'success' &&
|
||||
needs.test.result == 'success' &&
|
||||
needs.test_api_inventory_e2e.result == 'success'
|
||||
env:
|
||||
TG_BOT_KEY: ${{ secrets.TG_BOT_KEY }}
|
||||
TG_CHANNEL: ${{ secrets.TG_CHANNEL }}
|
||||
needs: [quality, build_push]
|
||||
if: ${{ always() && github.event_name != 'workflow_dispatch' }}
|
||||
|
||||
steps:
|
||||
- name: Telegram notify (lint+tests+e2e success)
|
||||
- name: Send CI status webhook
|
||||
continue-on-error: true
|
||||
env:
|
||||
COMMIT_MESSAGE: ${{ github.event.head_commit.message }}
|
||||
CI_NOTIFY_WEBHOOK_URL: ${{ secrets.CI_NOTIFY_WEBHOOK_URL }}
|
||||
CI_NOTIFY_TOKEN: ${{ secrets.CI_NOTIFY_TOKEN }}
|
||||
QUALITY_RESULT: ${{ needs.quality.result }}
|
||||
BUILD_PUSH_RESULT: ${{ needs.build_push.result }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [ -z "${TG_BOT_KEY:-}" ] || [ -z "${TG_CHANNEL:-}" ]; then
|
||||
echo "TG_BOT_KEY or TG_CHANNEL is not set; skip telegram notification"
|
||||
if [ -z "${CI_NOTIFY_WEBHOOK_URL:-}" ]; then
|
||||
echo "CI_NOTIFY_WEBHOOK_URL is not set; skip internal notification"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
MSG="✅ [mostovik-backend] lint + tests + api inventory e2e passed
|
||||
branch=${GITHUB_REF_NAME}
|
||||
sha=${GITHUB_SHA}
|
||||
actor=${GITHUB_ACTOR}
|
||||
commit=${COMMIT_MESSAGE:-n/a}"
|
||||
STATUS="success"
|
||||
if [ "${QUALITY_RESULT}" != "success" ]; then
|
||||
STATUS="${QUALITY_RESULT}"
|
||||
elif [ "${BUILD_PUSH_RESULT}" = "failure" ] || [ "${BUILD_PUSH_RESULT}" = "cancelled" ]; then
|
||||
STATUS="${BUILD_PUSH_RESULT}"
|
||||
fi
|
||||
export STATUS
|
||||
|
||||
PAYLOAD=$(python3 - <<'PY'
|
||||
import json
|
||||
import os
|
||||
|
||||
payload = {
|
||||
"project": os.environ.get("GITHUB_REPOSITORY"),
|
||||
"workflow": os.environ.get("GITHUB_WORKFLOW"),
|
||||
"status": os.environ.get("STATUS"),
|
||||
"branch": os.environ.get("GITHUB_HEAD_REF") or os.environ.get("GITHUB_REF_NAME"),
|
||||
"sha": os.environ.get("GITHUB_SHA"),
|
||||
"actor": os.environ.get("GITHUB_ACTOR"),
|
||||
"server_url": os.environ.get("GITHUB_SERVER_URL"),
|
||||
"run_id": os.environ.get("GITHUB_RUN_ID"),
|
||||
"results": {
|
||||
"quality": os.environ.get("QUALITY_RESULT"),
|
||||
"build_push": os.environ.get("BUILD_PUSH_RESULT"),
|
||||
},
|
||||
}
|
||||
print(json.dumps(payload, ensure_ascii=True, separators=(",", ":")))
|
||||
PY
|
||||
)
|
||||
|
||||
AUTH_HEADER=()
|
||||
if [ -n "${CI_NOTIFY_TOKEN:-}" ]; then
|
||||
AUTH_HEADER=(-H "Authorization: Bearer ${CI_NOTIFY_TOKEN}")
|
||||
fi
|
||||
|
||||
curl -fsS \
|
||||
--connect-timeout 5 \
|
||||
--max-time 15 \
|
||||
--retry 2 \
|
||||
--retry-delay 2 \
|
||||
--retry-all-errors \
|
||||
-X POST "https://api.telegram.org/bot${TG_BOT_KEY}/sendMessage" \
|
||||
-d "chat_id=${TG_CHANNEL}" \
|
||||
--data-urlencode "text=${MSG}" \
|
||||
|| echo "Telegram notification failed; continue pipeline"
|
||||
--connect-timeout 3 \
|
||||
--max-time 8 \
|
||||
--retry 1 \
|
||||
-H "Content-Type: application/json" \
|
||||
"${AUTH_HEADER[@]}" \
|
||||
--data "${PAYLOAD}" \
|
||||
"${CI_NOTIFY_WEBHOOK_URL}"
|
||||
|
||||
dokploy_dev_start:
|
||||
name: Start Dev Containers in Dokploy
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
if: ${{ github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/dev' }}
|
||||
|
||||
steps:
|
||||
- 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) ;;
|
||||
*)
|
||||
echo "dokploy_target must be one of: all, web, celery" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
call_webhook() {
|
||||
service_name="$1"
|
||||
webhook_url="$2"
|
||||
|
||||
if [ -z "${webhook_url}" ]; then
|
||||
echo "Dokploy webhook for ${service_name} is not configured" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
AUTH_HEADER=()
|
||||
if [ -n "${DOKPLOY_API_TOKEN:-}" ]; then
|
||||
AUTH_HEADER=(-H "Authorization: Bearer ${DOKPLOY_API_TOKEN}")
|
||||
fi
|
||||
|
||||
PAYLOAD=$(python3 - <<'PY'
|
||||
import json
|
||||
import os
|
||||
|
||||
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": "10.10.0.50/avm/mostovik-backend-web:dev",
|
||||
"celery": "10.10.0.50/avm/mostovik-backend-celery:dev",
|
||||
},
|
||||
}
|
||||
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}"
|
||||
}
|
||||
|
||||
triggered=0
|
||||
|
||||
if [ "${TARGET}" = "all" ] && [ -n "${DOKPLOY_DEV_WEBHOOK_URL:-}" ]; then
|
||||
CURRENT_DOKPLOY_TARGET="all" call_webhook "dev stack" "${DOKPLOY_DEV_WEBHOOK_URL}"
|
||||
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
|
||||
|
||||
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
|
||||
fi
|
||||
|
||||
if [ "${triggered}" -ne 1 ]; then
|
||||
echo "No Dokploy webhook was triggered" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
{
|
||||
echo "Dokploy dev trigger completed."
|
||||
echo "Target: ${TARGET}"
|
||||
echo "Web image: 10.10.0.50/avm/mostovik-backend-web:dev"
|
||||
echo "Celery image: 10.10.0.50/avm/mostovik-backend-celery:dev"
|
||||
} >> "${GITHUB_STEP_SUMMARY:-/dev/stdout}"
|
||||
|
||||
Reference in New Issue
Block a user