Add: Multiple auto-deploy solutions for OpenShift after GitHub Actions

This commit is contained in:
2025-09-25 18:40:31 -03:00
parent 6f6e4ed19d
commit e95f3e3f7c
4 changed files with 662 additions and 0 deletions

117
scripts/auto-deploy.sh Executable file
View 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
View 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)