Files
configure_nginx_manager/.github/workflows/deploy-service.yml
Workflow config file is invalid. Please check your config file: yaml: line 119: could not find expected ':'
Dmitriy Fofanov 90966663bf Добавлены улучшения для управления сертификатами и синхронизации Wiki
- Обновлены скрипты для поддержки групп сертификатов (SAN) в конфигурации.
- Добавлен новый скрипт для запуска GitHub Actions workflows.
- Обновлены Makefile и документация для отражения новых возможностей.
- Улучшена обработка доменов в коде и конфигурации.
2026-02-24 23:07:36 +03:00

239 lines
9.4 KiB
YAML

name: "Deploy scripts to remote server"
on:
workflow_dispatch:
inputs:
ref:
description: "Branch/tag/SHA for deployment"
required: false
default: "master"
jobs:
deploy:
name: "Upload and deploy on 192.168.10.14"
runs-on: native
steps:
- name: "Checkout repository"
shell: bash
env:
GIT_TOKEN: ${{ secrets.GIT_TOKEN }}
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
run: |
set -euo pipefail
TOKEN="${GIT_TOKEN:-$GITEA_TOKEN}"
if [ -z "${TOKEN}" ]; then
echo "ERROR: GIT_TOKEN (or GITEA_TOKEN) secret is required"
exit 1
fi
REF="${{ github.event.inputs.ref || 'master' }}"
SERVER="${{ github.server_url }}"
REPO="${{ github.repository }}"
HOST="${SERVER#https://}"
HOST="${HOST#http://}"
if [ "${HOST}" = "github.com" ]; then
CLONE_URL="https://x-access-token:${TOKEN}@${HOST}/${REPO}.git"
else
CLONE_URL="https://${TOKEN}@${HOST}/${REPO}.git"
fi
git clone --branch "${REF}" --depth 1 "${CLONE_URL}" . 2>&1 | grep -F -v "${TOKEN}" || true
echo ">>> Source checked out: $(git log --oneline -1)"
- name: "Validate deployment secrets"
shell: bash
env:
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
DEPLOY_PORT: ${{ secrets.DEPLOY_PORT }}
DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
DEPLOY_PATH: ${{ secrets.DEPLOY_PATH }}
DEPLOY_SERVICE: ${{ secrets.DEPLOY_SERVICE }}
DEPLOY_SSH_PRIVATE_KEY: ${{ secrets.DEPLOY_SSH_PRIVATE_KEY }}
DEPLOY_SSH_KNOWN_HOSTS: ${{ secrets.DEPLOY_SSH_KNOWN_HOSTS }}
CFG_REGRU_USERNAME: ${{ secrets.CFG_REGRU_USERNAME }}
CFG_REGRU_PASSWORD: ${{ secrets.CFG_REGRU_PASSWORD }}
CFG_EMAIL: ${{ secrets.CFG_EMAIL }}
CFG_DOMAINS: ${{ secrets.CFG_DOMAINS }}
run: |
set -euo pipefail
: "${DEPLOY_HOST:?DEPLOY_HOST secret is required}"
: "${DEPLOY_PORT:?DEPLOY_PORT secret is required}"
: "${DEPLOY_USER:?DEPLOY_USER secret is required}"
: "${DEPLOY_PATH:?DEPLOY_PATH secret is required}"
: "${DEPLOY_SERVICE:?DEPLOY_SERVICE secret is required}"
: "${DEPLOY_SSH_PRIVATE_KEY:?DEPLOY_SSH_PRIVATE_KEY secret is required}"
: "${CFG_REGRU_USERNAME:?CFG_REGRU_USERNAME secret is required}"
: "${CFG_REGRU_PASSWORD:?CFG_REGRU_PASSWORD secret is required}"
: "${CFG_EMAIL:?CFG_EMAIL secret is required}"
: "${CFG_DOMAINS:?CFG_DOMAINS secret is required}"
if [ "${DEPLOY_HOST}" != "192.168.10.14" ]; then
echo "ERROR: DEPLOY_HOST must be 192.168.10.14 for this workflow"
exit 1
fi
echo ">>> Secrets validation passed"
- name: "Create deployment archive"
shell: bash
env:
CFG_REGRU_USERNAME: ${{ secrets.CFG_REGRU_USERNAME }}
CFG_REGRU_PASSWORD: ${{ secrets.CFG_REGRU_PASSWORD }}
CFG_DOMAIN: ${{ secrets.CFG_DOMAIN }}
CFG_DOMAINS: ${{ secrets.CFG_DOMAINS }}
CFG_WILDCARD: ${{ secrets.CFG_WILDCARD }}
CFG_EMAIL: ${{ secrets.CFG_EMAIL }}
CFG_CERT_DIR: ${{ secrets.CFG_CERT_DIR }}
CFG_LOG_FILE: ${{ secrets.CFG_LOG_FILE }}
CFG_DNS_PROPAGATION_WAIT: ${{ secrets.CFG_DNS_PROPAGATION_WAIT }}
CFG_DNS_CHECK_ATTEMPTS: ${{ secrets.CFG_DNS_CHECK_ATTEMPTS }}
CFG_DNS_CHECK_INTERVAL: ${{ secrets.CFG_DNS_CHECK_INTERVAL }}
CFG_RENEWAL_DAYS: ${{ secrets.CFG_RENEWAL_DAYS }}
CFG_NPM_ENABLED: ${{ secrets.CFG_NPM_ENABLED }}
CFG_NPM_HOST: ${{ secrets.CFG_NPM_HOST }}
CFG_NPM_EMAIL: ${{ secrets.CFG_NPM_EMAIL }}
CFG_NPM_PASSWORD: ${{ secrets.CFG_NPM_PASSWORD }}
run: |
set -euo pipefail
rm -rf .deploy-artifacts
mkdir -p .deploy-artifacts
if command -v rsync >/dev/null 2>&1; then
rsync -a \
--exclude '.git/' \
--exclude '.src-repo/' \
--exclude '.wiki-repo/' \
--exclude '.deploy-artifacts/' \
./ .deploy-artifacts/repo/
else
cp -a . .deploy-artifacts/repo
rm -rf .deploy-artifacts/repo/.git .deploy-artifacts/repo/.src-repo .deploy-artifacts/repo/.wiki-repo .deploy-artifacts/repo/.deploy-artifacts
fi
python3 - <<'PY'
import json
import os
def to_bool(value, default=False):
if value is None or value == "":
return default
return str(value).strip().lower() in {"1", "true", "yes", "on"}
def to_int(value, default):
if value is None or value == "":
return default
return int(value)
domains_raw = os.environ.get("CFG_DOMAINS", "").strip()
if domains_raw.startswith("["):
# JSON array: каждый элемент может содержать запятые для SAN групп
# Пример: ["*.dfv24.com,dfv24.com", "github.dfv24.com"]
domains = json.loads(domains_raw)
else:
domains = [item.strip() for item in domains_raw.split(",") if item.strip()]
if not domains:
raise RuntimeError("CFG_DOMAINS must contain at least one domain")
# primary domain: первый домен из первой SAN группы
first_group_domains = [d.strip() for d in domains[0].split(",") if d.strip()]
domain = os.environ.get("CFG_DOMAIN", "").strip() or first_group_domains[0]
config = {
"regru_username": os.environ["CFG_REGRU_USERNAME"],
"regru_password": os.environ["CFG_REGRU_PASSWORD"],
"domain": domain,
"domains": domains,
"wildcard": to_bool(os.environ.get("CFG_WILDCARD"), True),
"email": os.environ["CFG_EMAIL"],
"cert_dir": os.environ.get("CFG_CERT_DIR") or "/etc/letsencrypt/live",
"log_file": os.environ.get("CFG_LOG_FILE") or "/var/log/letsencrypt_regru.log",
"dns_propagation_wait": to_int(os.environ.get("CFG_DNS_PROPAGATION_WAIT"), 60),
"dns_check_attempts": to_int(os.environ.get("CFG_DNS_CHECK_ATTEMPTS"), 10),
"dns_check_interval": to_int(os.environ.get("CFG_DNS_CHECK_INTERVAL"), 10),
"renewal_days": to_int(os.environ.get("CFG_RENEWAL_DAYS"), 30),
"npm_enabled": to_bool(os.environ.get("CFG_NPM_ENABLED"), True),
"npm_host": os.environ.get("CFG_NPM_HOST") or "",
"npm_email": os.environ.get("CFG_NPM_EMAIL") or "",
"npm_password": os.environ.get("CFG_NPM_PASSWORD") or "",
}
output_path = os.path.join(".deploy-artifacts", "repo", "config.json")
with open(output_path, "w", encoding="utf-8") as file:
json.dump(config, file, ensure_ascii=False, indent=4)
PY
tar -czf .deploy-artifacts/deploy.tar.gz -C .deploy-artifacts repo
ls -lh .deploy-artifacts/deploy.tar.gz
- name: "Configure SSH client"
shell: bash
env:
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
DEPLOY_PORT: ${{ secrets.DEPLOY_PORT }}
DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
DEPLOY_SSH_PRIVATE_KEY: ${{ secrets.DEPLOY_SSH_PRIVATE_KEY }}
DEPLOY_SSH_KNOWN_HOSTS: ${{ secrets.DEPLOY_SSH_KNOWN_HOSTS }}
run: |
set -euo pipefail
mkdir -p ~/.ssh
chmod 700 ~/.ssh
printf '%s\n' "${DEPLOY_SSH_PRIVATE_KEY}" > ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_ed25519
if [ -n "${DEPLOY_SSH_KNOWN_HOSTS}" ]; then
printf '%s\n' "${DEPLOY_SSH_KNOWN_HOSTS}" > ~/.ssh/known_hosts
else
ssh-keyscan -p "${DEPLOY_PORT}" -H "${DEPLOY_HOST}" >> ~/.ssh/known_hosts 2>/dev/null
fi
chmod 644 ~/.ssh/known_hosts
{
echo "Host deploy-target"
echo " HostName ${DEPLOY_HOST}"
echo " Port ${DEPLOY_PORT}"
echo " User ${DEPLOY_USER}"
echo " IdentityFile ~/.ssh/id_ed25519"
echo " StrictHostKeyChecking yes"
} > ~/.ssh/config
chmod 600 ~/.ssh/config
ssh deploy-target "echo '>>> SSH connection ok: ' \"\$(hostname)\""
- name: "Upload deployment archive"
shell: bash
run: |
set -euo pipefail
scp .deploy-artifacts/deploy.tar.gz deploy-target:/tmp/configure_nginx_manager_deploy.tar.gz
- name: "Deploy and restart remote service"
shell: bash
env:
DEPLOY_PATH: ${{ secrets.DEPLOY_PATH }}
DEPLOY_SERVICE: ${{ secrets.DEPLOY_SERVICE }}
run: |
set -euo pipefail
ssh deploy-target "set -euo pipefail; \
TMP_DIR=\"/tmp/configure_nginx_manager_deploy\"; \
sudo rm -rf \"\${TMP_DIR}\"; \
sudo mkdir -p \"\${TMP_DIR}\"; \
sudo tar -xzf /tmp/configure_nginx_manager_deploy.tar.gz -C \"\${TMP_DIR}\"; \
sudo mkdir -p \"${DEPLOY_PATH}\"; \
sudo rsync -a --delete --exclude '.git/' \"\${TMP_DIR}/repo/\" \"${DEPLOY_PATH}/\"; \
sudo rm -rf \"\${TMP_DIR}\" /tmp/configure_nginx_manager_deploy.tar.gz; \
sudo systemctl daemon-reload; \
sudo systemctl restart \"${DEPLOY_SERVICE}\"; \
sudo systemctl enable \"${DEPLOY_SERVICE}\"; \
sudo systemctl --no-pager --full status \"${DEPLOY_SERVICE}\" | head -n 30"