CI/CD
Intermediário
CI/CD GIT ACTIONS + SSH + WEBHOOK
Publicado em 23/03/2026
Contexto e Motivação
Sempre que realizava alterações no sistema, era necessário acessar o servidor manualmente para atualizar os arquivos, tornando o processo lento e suscetível a erros.
Para resolver isso, implementei uma automação de deploy utilizando GitHub Actions, onde a cada push na branch principal o processo é executado automaticamente. A comunicação com o servidor é feita via SSH, garantindo segurança na execução dos comandos remotos.
Também integrei Webhooks para envio de notificações em tempo real sobre o status do deploy (sucesso ou falha), direcionadas para um canal no Discord, permitindo acompanhamento contínuo sem necessidade de acesso direto ao servidor.
Todo o fluxo foi configurado no arquivo .github/workflows/deploy.yml, e as credenciais sensíveis foram isoladas utilizando variáveis de ambiente do GitHub, garantindo maior segurança.
Para resolver isso, implementei uma automação de deploy utilizando GitHub Actions, onde a cada push na branch principal o processo é executado automaticamente. A comunicação com o servidor é feita via SSH, garantindo segurança na execução dos comandos remotos.
Também integrei Webhooks para envio de notificações em tempo real sobre o status do deploy (sucesso ou falha), direcionadas para um canal no Discord, permitindo acompanhamento contínuo sem necessidade de acesso direto ao servidor.
Todo o fluxo foi configurado no arquivo .github/workflows/deploy.yml, e as credenciais sensíveis foram isoladas utilizando variáveis de ambiente do GitHub, garantindo maior segurança.
Implementação
name: Deploy # Define o nome do workflow que aparecerá na interface do GitHub Actions
on:
push:
branches:
- main # Dispara o deploy automaticamente sempre que houver um push na branch de produção
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true # Garante compatibilidade das actions com a versão mais recente do Node.js no runner
jobs:
deploy:
name: Update Portfólio
runs-on: ubuntu-latest # Utiliza uma máquina virtual Linux limpa para executar o processo
environment: portifolio # Associa o job a um ambiente específico para gerenciar segredos de forma isolada
steps:
- name: Checkout code
uses: actions/checkout@v4.2.2 # Baixa o código fonte do repositório para o runner do GitHub
- name: Configure SSH Agent
uses: webfactory/ssh-agent@v0.9.1 # Gerencia a chave privada SSH para autenticação segura sem senha
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
- name: Add server to known_hosts
run: |
mkdir -p ~/.ssh
echo "StrictHostKeyChecking no" >> ~/.ssh/config # Evita que o script pare pedindo confirmação manual da identidade do servidor
- name: Sync files to server
run: |
rsync -avz --delete \
--exclude='.git/' \
--exclude='.github/' \
--exclude='.env' \
--exclude='*.log' \
--exclude='vendor/' \
-e "ssh -p ${{ secrets.SSH_PORT }} -o StrictHostKeyChecking=no" \
./ ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }}:${{ secrets.REMOTE_PATH }}/ # Sincroniza apenas arquivos alterados e remove deletados, otimizando o tempo de deploy
- name: Create .env file on server
run: |
ssh -p ${{ secrets.SSH_PORT }} -o StrictHostKeyChecking=no ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} "cat > ${{ secrets.REMOTE_PATH }}/.env" << 'EOF'
APP_NAME=${{ secrets.APP_NAME }}
DB_HOST=${{ secrets.DB_HOST }}
DB_NAME=${{ secrets.DB_NAME }}
DB_USER=${{ secrets.DB_USER }}
DB_PASS=${{ secrets.DB_PASS }}
MAIL_HOST=${{ secrets.MAIL_HOST }}
MAIL_PORT=${{ secrets.MAIL_PORT }}
MAIL_USER=${{ secrets.MAIL_USER }}
MAIL_PASS=${{ secrets.MAIL_PASS }}
MAIL_FROM_NAME=${{ secrets.MAIL_FROM_NAME }}
MAIL_FROM_ADDRESS=${{ secrets.MAIL_FROM_ADDRESS }}
MAIL_TO_ADDRESS=${{ secrets.MAIL_TO_ADDRESS }}
MAIL_ENCRYPTION=${{ secrets.MAIL_ENCRYPTION }}
EOF # Reconstrói o arquivo de ambiente no servidor usando os segredos protegidos do GitHub
- name: Pós-deploy
run: |
ssh -p ${{ secrets.SSH_PORT }} -o StrictHostKeyChecking=no ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} << 'EOF'
cd ${{ secrets.REMOTE_PATH }}
composer install --no-dev --optimize-autoloader # Instala dependências de produção e otimiza o carregamento das classes
php migrate.php # Executa migrações de banco de dados para manter o esquema atualizado
EOF
- name: Deploy Confirmation
run: echo "Deploy successful!"
- name: Notify Discord
uses: rjstone/discord-webhook-notify@v2
if: always() # Garante que a notificação seja enviada tanto em caso de sucesso quanto em falha
with:
severity: ${{ job.status == 'success' && 'info' || 'error' }}
details: ${{ job.status == 'success' && 'Deploy realizado com sucesso na branch Main!' || 'Falha no Deploy!' }}
webhookUrl: ${{ secrets.DISCORD_WEBHOOK }}
username: 'GitHub Action Bot' # Automatiza o feedback visual no Discord, evitando a necessidade de monitorar o painel do GitHub constantemente
Decisão Técnica
Automatizar o deploy com GitHub Actions elimina a necessidade de acesso manual ao servidor, reduzindo erros humanos e aumentando a velocidade de entrega. O uso de SSH permite uma comunicação segura e direta com o servidor de produção, mantendo o controle total do processo sem depender de ferramentas externas mais complexas.
A integração com Webhook foi adotada para fornecer feedback imediato sobre o status do deploy (sucesso ou falha), melhorando a visibilidade e permitindo ações rápidas em caso de erro. O envio dessas notificações para o Discord foi uma escolha prática, pois é uma ferramenta já presente no fluxo diário.
Além disso, a utilização de variáveis de ambiente no GitHub Actions garante maior segurança, evitando exposição de credenciais sensíveis no repositório.
A integração com Webhook foi adotada para fornecer feedback imediato sobre o status do deploy (sucesso ou falha), melhorando a visibilidade e permitindo ações rápidas em caso de erro. O envio dessas notificações para o Discord foi uma escolha prática, pois é uma ferramenta já presente no fluxo diário.
Além disso, a utilização de variáveis de ambiente no GitHub Actions garante maior segurança, evitando exposição de credenciais sensíveis no repositório.
Tecnologias
#CI/CD
#GitHub Actions
#Deploy Automatizado
#SSH
#Webhook
#DevOps
#Segurança