diff --git a/.gitea/workflows/deploy-customer-main.yml b/.gitea/workflows/deploy-customer-main.yml new file mode 100644 index 0000000..5560e2e --- /dev/null +++ b/.gitea/workflows/deploy-customer-main.yml @@ -0,0 +1,169 @@ +name: Deploy Customer Main + +on: + push: + branches: + - main + workflow_dispatch: + +concurrency: + group: mostovik-backend-customer-main-${{ github.ref }} + cancel-in-progress: true + +env: + CUSTOMER_REGISTRY_HOST: registry.dev.nii-ecos.ru:80 + CUSTOMER_REGISTRY_NAMESPACE: avm + CUSTOMER_WEB_IMAGE: mostovik-backend-web + CUSTOMER_CELERY_IMAGE: mostovik-backend-celery + CUSTOMER_DEPLOY_USER: ecos + CUSTOMER_DEPLOY_HOST: 10.0.10.174 + CUSTOMER_SSH_PROXY_HOST: root@10.10.0.121 + CUSTOMER_COMPOSE_FILE: /ecos/docker-compose.yml + CUSTOMER_DEPLOY_SCRIPT: /ecos/pull-and-run.sh + +jobs: + deploy: + name: Build, Push, Deploy + runs-on: ubuntu-latest + timeout-minutes: 90 + + steps: + - name: Ensure main branch + run: | + set -euo pipefail + if [ "${GITHUB_REF_NAME}" != "main" ]; then + echo "Customer deploy is allowed only from main; current ref is ${GITHUB_REF_NAME}" >&2 + exit 1 + fi + + - name: Checkout code + run: | + set -euo pipefail + REPO_URL="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}.git" + BRANCH="${GITHUB_HEAD_REF:-${GITHUB_REF_NAME}}" + git -c core.hooksPath=/dev/null clone --depth=1 --branch="${BRANCH}" "${REPO_URL}" . + git -c core.hooksPath=/dev/null checkout "${GITHUB_SHA}" + + - name: Validate deploy inputs + env: + REGISTRY_USER: ${{ secrets.REGISTRY_USER }} + REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }} + REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }} + REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }} + CUSTOMER_DEPLOY_SSH_KEY: ${{ secrets.CUSTOMER_DEPLOY_SSH_KEY }} + CUSTOMER_DEPLOY_SSH_KEY_B64: ${{ secrets.CUSTOMER_DEPLOY_SSH_KEY_B64 }} + DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }} + run: | + set -euo pipefail + + registry_user="${REGISTRY_USER:-${REGISTRY_USERNAME:-}}" + registry_password="${REGISTRY_TOKEN:-${REGISTRY_PASSWORD:-}}" + + if [ -z "${registry_user}" ]; then + echo "Missing registry user secret: set REGISTRY_USER or REGISTRY_USERNAME" >&2 + exit 1 + fi + if [ -z "${registry_password}" ]; then + echo "Missing registry password secret: set REGISTRY_TOKEN or REGISTRY_PASSWORD" >&2 + exit 1 + fi + if [ -z "${CUSTOMER_DEPLOY_SSH_KEY:-}" ] \ + && [ -z "${CUSTOMER_DEPLOY_SSH_KEY_B64:-}" ] \ + && [ -z "${DEPLOY_SSH_KEY:-}" ] \ + && [ ! -f "${HOME}/.ssh/ci-key" ] \ + && [ ! -f "/root/.ssh/ci-key" ]; then + echo "Missing customer SSH key: set CUSTOMER_DEPLOY_SSH_KEY_B64, CUSTOMER_DEPLOY_SSH_KEY, DEPLOY_SSH_KEY, or install ~/.ssh/ci-key on the runner" >&2 + exit 1 + fi + + - name: Install crane + run: | + set -euo pipefail + curl -fsSL https://github.com/google/go-containerregistry/releases/download/v0.19.0/go-containerregistry_Linux_x86_64.tar.gz \ + | tar xz crane + chmod +x crane + + - name: Build and push customer images + env: + REGISTRY_USER: ${{ secrets.REGISTRY_USER }} + REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }} + REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }} + REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }} + run: | + set -euo pipefail + + registry_user="${REGISTRY_USER:-${REGISTRY_USERNAME:-}}" + registry_password="${REGISTRY_TOKEN:-${REGISTRY_PASSWORD:-}}" + sha_short="$(printf '%s' "${GITHUB_SHA}" | cut -c1-12)" + registry_path="${CUSTOMER_REGISTRY_HOST}/${CUSTOMER_REGISTRY_NAMESPACE}" + web_ref="${registry_path}/${CUSTOMER_WEB_IMAGE}" + celery_ref="${registry_path}/${CUSTOMER_CELERY_IMAGE}" + + printf '%s' "${registry_password}" \ + | ./crane auth login --insecure "${CUSTOMER_REGISTRY_HOST}" \ + -u "${registry_user}" \ + --password-stdin + + docker build \ + --platform linux/amd64 \ + -f ./docker/Dockerfile \ + --target runtime-web \ + --build-arg INSTALL_DEV=false \ + -t customer-mostovik-backend-web:local \ + . + docker save customer-mostovik-backend-web:local -o /tmp/customer-mostovik-backend-web.tar + ./crane push --insecure /tmp/customer-mostovik-backend-web.tar "${web_ref}:latest" + ./crane push --insecure /tmp/customer-mostovik-backend-web.tar "${web_ref}:${sha_short}" + + docker build \ + --platform linux/amd64 \ + -f ./docker/Dockerfile \ + --target runtime-celery \ + --build-arg INSTALL_DEV=false \ + -t customer-mostovik-backend-celery:local \ + . + docker save customer-mostovik-backend-celery:local -o /tmp/customer-mostovik-backend-celery.tar + ./crane push --insecure /tmp/customer-mostovik-backend-celery.tar "${celery_ref}:latest" + ./crane push --insecure /tmp/customer-mostovik-backend-celery.tar "${celery_ref}:${sha_short}" + + - name: Deploy customer stack + env: + CUSTOMER_DEPLOY_SSH_KEY: ${{ secrets.CUSTOMER_DEPLOY_SSH_KEY }} + CUSTOMER_DEPLOY_SSH_KEY_B64: ${{ secrets.CUSTOMER_DEPLOY_SSH_KEY_B64 }} + DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }} + run: | + set -euo pipefail + + mkdir -p "${HOME}/.ssh" + key_path="${HOME}/.ssh/customer_deploy_key" + if [ -n "${CUSTOMER_DEPLOY_SSH_KEY_B64:-}" ]; then + printf '%s' "${CUSTOMER_DEPLOY_SSH_KEY_B64}" | base64 -d > "${key_path}" + elif [ -n "${DEPLOY_SSH_KEY:-}" ]; then + printf '%s' "${DEPLOY_SSH_KEY}" | base64 -d > "${key_path}" + elif [ -n "${CUSTOMER_DEPLOY_SSH_KEY:-}" ]; then + printf '%s\n' "${CUSTOMER_DEPLOY_SSH_KEY}" > "${key_path}" + elif [ -f "${HOME}/.ssh/ci-key" ]; then + cp "${HOME}/.ssh/ci-key" "${key_path}" + else + cp "/root/.ssh/ci-key" "${key_path}" + fi + chmod 600 "${key_path}" + + ssh_common=( + -i "${key_path}" + -o BatchMode=yes + -o IdentitiesOnly=yes \ + -o StrictHostKeyChecking=no + -o UserKnownHostsFile=/dev/null + -o GlobalKnownHostsFile=/dev/null + -o LogLevel=ERROR + -o ConnectTimeout=15 + ) + proxy_command="ssh -i ${key_path} -o BatchMode=yes -o IdentitiesOnly=yes -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o GlobalKnownHostsFile=/dev/null -o LogLevel=ERROR -o ConnectTimeout=15 -W %h:%p ${CUSTOMER_SSH_PROXY_HOST}" + remote_command="set -euo pipefail + cd /ecos + FORCE_PULL=1 COMPOSE_FILE='${CUSTOMER_COMPOSE_FILE}' '${CUSTOMER_DEPLOY_SCRIPT}' + docker image prune -f" + + ssh "${ssh_common[@]}" -o "ProxyCommand=${proxy_command}" "${CUSTOMER_DEPLOY_USER}@${CUSTOMER_DEPLOY_HOST}" "true" + ssh "${ssh_common[@]}" -o "ProxyCommand=${proxy_command}" "${CUSTOMER_DEPLOY_USER}@${CUSTOMER_DEPLOY_HOST}" "${remote_command}"