Files
2026-06-16 09:19:32 +03:00

142 lines
4.6 KiB
Groovy

// Home AI Assistant — деплой на Linux (Docker).
//
// Нода: label linux
//
// Реальный путь репо (не symlink): /srv/storage/disk2/services/Home_assistant
// ~/to_services/Home_assistant может быть ссылкой на него.
//
// Права jenkins (один раз):
// sudo usermod -aG docker jenkins
// sudo setfacl -m u:jenkins:rx /home/grigo /home/grigo/to_services
// sudo setfacl -R -m u:jenkins:rwX /srv/storage/disk2/services/Home_assistant
pipeline {
agent {
label 'linux'
}
options {
buildDiscarder(logRotator(numToKeepStr: '25'))
timeout(time: 45, unit: 'MINUTES')
disableConcurrentBuilds()
timestamps()
}
parameters {
string(
name: 'GIT_BRANCH',
defaultValue: 'main',
description: 'Ветка: git reset --hard origin/<branch>'
)
string(
name: 'DEPLOY_DIR',
defaultValue: '/srv/storage/disk2/services/Home_assistant',
description: 'Каталог деплоя (.env, data/, docker-compose.yml)'
)
string(
name: 'BACKEND_HEALTH_URL',
defaultValue: 'http://127.0.0.1:8202/api/v1/health',
description: 'Healthcheck после деплоя'
)
booleanParam(
name: 'DOCKER_PULL',
defaultValue: true,
description: 'docker compose build --pull'
)
}
environment {
GIT_BRANCH = "${params.GIT_BRANCH}"
DEPLOY_DIR = "${params.DEPLOY_DIR}"
BACKEND_HEALTH_URL = "${params.BACKEND_HEALTH_URL}"
DOCKER_PULL = "${params.DOCKER_PULL}"
}
stages {
stage('Preflight') {
steps {
sh '''
set -euxo pipefail
REPO_DIR=$(readlink -f "${DEPLOY_DIR}")
echo "REPO_DIR=${REPO_DIR}"
command -v docker
docker compose version
test -d "${REPO_DIR}"
test -r "${REPO_DIR}"
test -w "${REPO_DIR}"
test -f "${REPO_DIR}/.env"
test -f "${REPO_DIR}/docker-compose.yml"
# git от jenkins: владелец репо — grigo
git config --global --add safe.directory "${REPO_DIR}"
'''
}
}
stage('Deploy') {
steps {
sh '''
set -euxo pipefail
REPO_DIR=$(readlink -f "${DEPLOY_DIR}")
git config --global --add safe.directory "${REPO_DIR}"
cd "${REPO_DIR}"
git fetch --prune origin
git reset --hard "origin/${GIT_BRANCH}"
git clean -fd -e .env -e data -e 'data/**'
docker compose build backend
docker compose run --rm --no-deps backend \
sh -c 'pip install -q -r requirements-dev.txt && pytest tests/ -q --tb=short'
if [ "${DOCKER_PULL}" = "true" ]; then
docker compose build --pull
else
docker compose build
fi
docker compose up -d
docker compose ps
'''
}
}
stage('Healthcheck') {
steps {
sh '''
set -euxo pipefail
for i in $(seq 1 30); do
if curl -fsS "${BACKEND_HEALTH_URL}" >/dev/null; then
echo "OK: ${BACKEND_HEALTH_URL}"
exit 0
fi
sleep 2
done
echo "Healthcheck failed: ${BACKEND_HEALTH_URL}"
exit 1
'''
}
}
}
post {
success {
echo "Deployed ${DEPLOY_DIR} @ origin/${GIT_BRANCH}"
}
failure {
sh '''
REPO_DIR=$(readlink -f "${DEPLOY_DIR}" 2>/dev/null || echo "${DEPLOY_DIR}")
if [ -d "${REPO_DIR}" ] && [ -r "${REPO_DIR}" ]; then
cd "${REPO_DIR}"
docker compose ps || true
docker compose logs --tail=100 backend || true
docker compose logs --tail=50 frontend || true
else
echo "Нет доступа к ${REPO_DIR}"
fi
'''
}
}
}