Add: Multiple auto-deploy solutions for OpenShift after GitHub Actions
This commit is contained in:
117
scripts/auto-deploy.sh
Executable file
117
scripts/auto-deploy.sh
Executable file
@@ -0,0 +1,117 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Script para deploy automático após GitHub Actions
|
||||
# Este script pode ser executado localmente ou via webhook
|
||||
|
||||
set -e
|
||||
|
||||
# Cores para output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Configurações
|
||||
IMAGE_NAME="resource-governance"
|
||||
REGISTRY="andersonid"
|
||||
NAMESPACE="resource-governance"
|
||||
IMAGE_TAG=${1:-latest}
|
||||
|
||||
echo -e "${BLUE}🚀 Auto-Deploy para OpenShift${NC}"
|
||||
echo "================================"
|
||||
echo "Imagem: ${REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG}"
|
||||
echo "Namespace: ${NAMESPACE}"
|
||||
echo ""
|
||||
|
||||
# 1. Verificar login no OpenShift
|
||||
if ! oc whoami > /dev/null 2>&1; then
|
||||
echo -e "${RED}❌ Não logado no OpenShift. Por favor, faça login com 'oc login'.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
echo -e "${GREEN}✅ Logado no OpenShift como: $(oc whoami)${NC}"
|
||||
echo ""
|
||||
|
||||
# 2. Verificar se a imagem existe no Docker Hub
|
||||
echo -e "${BLUE}🔍 Verificando imagem no Docker Hub...${NC}"
|
||||
if ! skopeo inspect docker://${REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG} > /dev/null 2>&1; then
|
||||
echo -e "${RED}❌ Imagem ${REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG} não encontrada no Docker Hub!${NC}"
|
||||
exit 1
|
||||
fi
|
||||
echo -e "${GREEN}✅ Imagem encontrada no Docker Hub${NC}"
|
||||
echo ""
|
||||
|
||||
# 3. Verificar se o namespace existe
|
||||
if ! oc get namespace ${NAMESPACE} > /dev/null 2>&1; then
|
||||
echo -e "${BLUE}📋 Criando namespace ${NAMESPACE}...${NC}"
|
||||
oc create namespace ${NAMESPACE}
|
||||
else
|
||||
echo -e "${GREEN}✅ Namespace ${NAMESPACE} já existe${NC}"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# 4. Aplicar manifests básicos
|
||||
echo -e "${BLUE}📋 Aplicando manifests básicos...${NC}"
|
||||
oc apply -f k8s/rbac.yaml -n ${NAMESPACE}
|
||||
oc apply -f k8s/configmap.yaml -n ${NAMESPACE}
|
||||
echo ""
|
||||
|
||||
# 5. Verificar se o deployment existe
|
||||
if oc get deployment ${IMAGE_NAME} -n ${NAMESPACE} > /dev/null 2>&1; then
|
||||
echo -e "${BLUE}🔄 Deployment existente encontrado. Iniciando atualização...${NC}"
|
||||
|
||||
# Obter imagem atual
|
||||
CURRENT_IMAGE=$(oc get deployment ${IMAGE_NAME} -n ${NAMESPACE} -o jsonpath='{.spec.template.spec.containers[0].image}')
|
||||
echo "Imagem atual: ${CURRENT_IMAGE}"
|
||||
echo "Nova imagem: ${REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG}"
|
||||
|
||||
# Verificar se a imagem mudou
|
||||
if [ "${CURRENT_IMAGE}" = "${REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG}" ]; then
|
||||
echo -e "${YELLOW}⚠️ Imagem já está atualizada. Nenhuma ação necessária.${NC}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Atualizar deployment com nova imagem
|
||||
echo -e "${BLUE}🔄 Atualizando imagem do deployment...${NC}"
|
||||
oc set image deployment/${IMAGE_NAME} ${IMAGE_NAME}=${REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG} -n ${NAMESPACE}
|
||||
|
||||
# Aguardar rollout
|
||||
echo -e "${BLUE}⏳ Aguardando rollout (pode levar alguns minutos)...${NC}"
|
||||
oc rollout status deployment/${IMAGE_NAME} -n ${NAMESPACE} --timeout=300s
|
||||
echo -e "${GREEN}✅ Rollout concluído com sucesso!${NC}"
|
||||
|
||||
else
|
||||
echo -e "${BLUE}📦 Deployment não encontrado. Criando novo deployment...${NC}"
|
||||
# Aplicar deployment, service e route
|
||||
oc apply -f k8s/deployment.yaml -n ${NAMESPACE}
|
||||
oc apply -f k8s/service.yaml -n ${NAMESPACE}
|
||||
oc apply -f k8s/route.yaml -n ${NAMESPACE}
|
||||
|
||||
# Aguardar rollout inicial
|
||||
echo -e "${BLUE}⏳ Aguardando rollout inicial...${NC}"
|
||||
oc rollout status deployment/${IMAGE_NAME} -n ${NAMESPACE} --timeout=300s
|
||||
echo -e "${GREEN}✅ Rollout inicial concluído com sucesso!${NC}"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# 6. Verificar status final
|
||||
echo -e "${BLUE}📊 STATUS FINAL:${NC}"
|
||||
echo "================"
|
||||
oc get deployment ${IMAGE_NAME} -n ${NAMESPACE}
|
||||
echo ""
|
||||
oc get pods -n ${NAMESPACE} -l app.kubernetes.io/name=${IMAGE_NAME}
|
||||
echo ""
|
||||
|
||||
# 7. Obter URLs de acesso
|
||||
ROUTE_URL=$(oc get route ${IMAGE_NAME}-route -n ${NAMESPACE} -o jsonpath='{.spec.host}' 2>/dev/null || echo "")
|
||||
echo -e "${BLUE}🌐 URLs de acesso:${NC}"
|
||||
if [ -n "$ROUTE_URL" ]; then
|
||||
echo " OpenShift: https://$ROUTE_URL"
|
||||
else
|
||||
echo " OpenShift: Rota não encontrada ou não disponível."
|
||||
fi
|
||||
echo " Port-forward: http://localhost:8080 (se ativo)"
|
||||
echo ""
|
||||
|
||||
echo -e "${GREEN}✅ Auto-deploy concluído com sucesso!${NC}"
|
||||
echo -e "${BLUE}🔄 Estratégia: Rolling Update com maxUnavailable=0 (zero downtime)${NC}"
|
||||
180
scripts/webhook-deploy.py
Executable file
180
scripts/webhook-deploy.py
Executable file
@@ -0,0 +1,180 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Webhook para deploy automático após GitHub Actions
|
||||
Este script pode ser executado como um serviço para detectar mudanças no Docker Hub
|
||||
"""
|
||||
|
||||
import os
|
||||
import json
|
||||
import subprocess
|
||||
import logging
|
||||
from flask import Flask, request, jsonify
|
||||
from datetime import datetime
|
||||
|
||||
# Configuração do logging
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
# Configurações
|
||||
IMAGE_NAME = os.getenv('IMAGE_NAME', 'resource-governance')
|
||||
REGISTRY = os.getenv('REGISTRY', 'andersonid')
|
||||
NAMESPACE = os.getenv('NAMESPACE', 'resource-governance')
|
||||
SCRIPT_PATH = os.getenv('AUTO_DEPLOY_SCRIPT', './scripts/auto-deploy.sh')
|
||||
|
||||
@app.route('/webhook/dockerhub', methods=['POST'])
|
||||
def dockerhub_webhook():
|
||||
"""Webhook para receber notificações do Docker Hub"""
|
||||
try:
|
||||
data = request.get_json()
|
||||
|
||||
# Verificar se é uma notificação de push
|
||||
if data.get('push_data', {}).get('tag') == 'latest':
|
||||
logger.info(f"Recebida notificação de push para {REGISTRY}/{IMAGE_NAME}:latest")
|
||||
|
||||
# Executar deploy automático
|
||||
result = run_auto_deploy('latest')
|
||||
|
||||
return jsonify({
|
||||
'status': 'success',
|
||||
'message': 'Deploy automático iniciado',
|
||||
'result': result
|
||||
}), 200
|
||||
else:
|
||||
logger.info(f"Push ignorado - tag: {data.get('push_data', {}).get('tag')}")
|
||||
return jsonify({'status': 'ignored', 'message': 'Tag não é latest'}), 200
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Erro no webhook: {e}")
|
||||
return jsonify({'status': 'error', 'message': str(e)}), 500
|
||||
|
||||
@app.route('/webhook/github', methods=['POST'])
|
||||
def github_webhook():
|
||||
"""Webhook para receber notificações do GitHub"""
|
||||
try:
|
||||
# Verificar se é um push para main
|
||||
if request.headers.get('X-GitHub-Event') == 'push':
|
||||
data = request.get_json()
|
||||
|
||||
if data.get('ref') == 'refs/heads/main':
|
||||
logger.info("Recebida notificação de push para main branch")
|
||||
|
||||
# Executar deploy automático
|
||||
result = run_auto_deploy('latest')
|
||||
|
||||
return jsonify({
|
||||
'status': 'success',
|
||||
'message': 'Deploy automático iniciado',
|
||||
'result': result
|
||||
}), 200
|
||||
else:
|
||||
logger.info(f"Push ignorado - branch: {data.get('ref')}")
|
||||
return jsonify({'status': 'ignored', 'message': 'Branch não é main'}), 200
|
||||
else:
|
||||
logger.info(f"Evento ignorado: {request.headers.get('X-GitHub-Event')}")
|
||||
return jsonify({'status': 'ignored', 'message': 'Evento não é push'}), 200
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Erro no webhook: {e}")
|
||||
return jsonify({'status': 'error', 'message': str(e)}), 500
|
||||
|
||||
@app.route('/deploy/<tag>', methods=['POST'])
|
||||
def manual_deploy(tag):
|
||||
"""Deploy manual com tag específica"""
|
||||
try:
|
||||
logger.info(f"Deploy manual solicitado para tag: {tag}")
|
||||
|
||||
result = run_auto_deploy(tag)
|
||||
|
||||
return jsonify({
|
||||
'status': 'success',
|
||||
'message': f'Deploy manual iniciado para tag: {tag}',
|
||||
'result': result
|
||||
}), 200
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Erro no deploy manual: {e}")
|
||||
return jsonify({'status': 'error', 'message': str(e)}), 500
|
||||
|
||||
def run_auto_deploy(tag):
|
||||
"""Executar script de deploy automático"""
|
||||
try:
|
||||
logger.info(f"Executando deploy automático para tag: {tag}")
|
||||
|
||||
# Executar script de deploy
|
||||
result = subprocess.run(
|
||||
[SCRIPT_PATH, tag],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=600 # 10 minutos timeout
|
||||
)
|
||||
|
||||
if result.returncode == 0:
|
||||
logger.info("Deploy automático concluído com sucesso")
|
||||
return {
|
||||
'success': True,
|
||||
'stdout': result.stdout,
|
||||
'stderr': result.stderr
|
||||
}
|
||||
else:
|
||||
logger.error(f"Deploy automático falhou: {result.stderr}")
|
||||
return {
|
||||
'success': False,
|
||||
'stdout': result.stdout,
|
||||
'stderr': result.stderr
|
||||
}
|
||||
|
||||
except subprocess.TimeoutExpired:
|
||||
logger.error("Deploy automático timeout")
|
||||
return {
|
||||
'success': False,
|
||||
'error': 'Timeout'
|
||||
}
|
||||
except Exception as e:
|
||||
logger.error(f"Erro ao executar deploy automático: {e}")
|
||||
return {
|
||||
'success': False,
|
||||
'error': str(e)
|
||||
}
|
||||
|
||||
@app.route('/health', methods=['GET'])
|
||||
def health():
|
||||
"""Health check"""
|
||||
return jsonify({
|
||||
'status': 'healthy',
|
||||
'timestamp': datetime.now().isoformat(),
|
||||
'image': f'{REGISTRY}/{IMAGE_NAME}',
|
||||
'namespace': NAMESPACE
|
||||
}), 200
|
||||
|
||||
@app.route('/status', methods=['GET'])
|
||||
def status():
|
||||
"""Status do serviço"""
|
||||
try:
|
||||
# Verificar se está logado no OpenShift
|
||||
result = subprocess.run(['oc', 'whoami'], capture_output=True, text=True)
|
||||
|
||||
return jsonify({
|
||||
'status': 'running',
|
||||
'timestamp': datetime.now().isoformat(),
|
||||
'openshift_user': result.stdout.strip() if result.returncode == 0 else 'Not logged in',
|
||||
'image': f'{REGISTRY}/{IMAGE_NAME}',
|
||||
'namespace': NAMESPACE,
|
||||
'script_path': SCRIPT_PATH
|
||||
}), 200
|
||||
|
||||
except Exception as e:
|
||||
return jsonify({
|
||||
'status': 'error',
|
||||
'message': str(e)
|
||||
}), 500
|
||||
|
||||
if __name__ == '__main__':
|
||||
port = int(os.getenv('PORT', 8080))
|
||||
debug = os.getenv('DEBUG', 'false').lower() == 'true'
|
||||
|
||||
logger.info(f"Iniciando webhook server na porta {port}")
|
||||
logger.info(f"Configurações: IMAGE_NAME={IMAGE_NAME}, REGISTRY={REGISTRY}, NAMESPACE={NAMESPACE}")
|
||||
|
||||
app.run(host='0.0.0.0', port=port, debug=debug)
|
||||
Reference in New Issue
Block a user