Estou tentando integrar o Fluig com o GitHub Actions, já criei o runner e configurei tudo corretamente, porém a lógica de dar deploy automaticamente no Fluig era usar o próprio JBoss ao meu favor, eu gero o .war via um script powershell que eu fiz (o que gera corretamente pois ao upar o componente via UI do Fluig, a widget upa corretamente) porém ao tentar colocar ele no /deployments/ o JBoss não dá o deploy automático, mesmo rodando o script do JBoss manualmente também… alguém já tentou isso?
Não sei se simplesmente colocar na pasta de deployments ou apps, direto no servidor Fluig, efetuaria o deploy automaticamente (conheço pouco da arquitetura Java / JBoss / WildFly).
Mas tenta jogar na pasta apps pra ver se dispara algo para o Fluig. Ao menos ao reiniciar o serviço já vi que ele vasculha a pasta apps pra validar as instalações dos componentes.
Acho que ao efetuar o deploy via a API do Fluig (mesmo que seja na Central de Componentes) o Fluig execute alguns processos em background para finalizar o deploy, até considerando que existem eventos possíveis pra inserir nos componentes para ser executado durante a instalação/habilitação/desativação etc.
eu fiz muito a grosso modo ali em cima de dizer que simplesmente taquei na pasta e não foi, na verdade eu tinha um observador que triggava com a action do runner do git e rodava esse comando:
/opt/fluig/appserver/bin/jboss-cli.sh -c --command="deploy /opt/fluig/appserver/standalone/deployments/nome_da_widget.war --all-server-groups --force"
e eu não sei porque esse comando não estava funcionando, e eu tentei procurar algo pra enviar via API mas aparentemente a TOTVS não estava muito afim de mostrar como que a API poderia ser consumida por fora do Fluig kkkkkkkk
esse arquivo jboss-cli.sh é o que faz o deploy, inclusive se você tiver acesso ao seu fluig, pode ver que na pasta deployments/ vai ter um readme explicando como funciona o deploy e os seus sufixos
Salve @kysozin
sempre que cloquei projetos .war dentro da pasta /appserver/apps o deploy foi feito automaticamente.
Aplicativos customizados
Se possuir aplicativos não padrão, sejam desenvolvidos por equipes internas, por terceiros ou mesmo baixado na Store oficial do Fluig, esses estarão na pasta própria.
Em uma instalação padrão, encontram-se na pasta “appserver/apps”.
Esses aplicativos precisam ser disponibilizados manualmente para a nova instalação.
Em uma instalação padrão, com um único servidor Fluig, basta copiar o conteúdo da pasta apps do servidor atual (por exemplo: C:\fluig\appserver\apps) para a pasta apps do novo servidor (por exemplo: /opt/fluig/appserver/apps).
entendi @fluigor.com.br, porém ainda estou com uma dúvida, se eu simplesmente colocar o .war dentro do /opt/fluig/appserver/apps (um que eu criei do 0) ele vai fazer o deploy automático dentro do fluig? ou eu preciso criar e direcionar ele pra uma pasta /apps/{pasta_da_widget_nova}?
Consegui upar as widgets pelo /apps normal, valeu !
Jogando a widget direto na pasta Apps precisará ativar a widget no Painel de Controle, certo?
O diferencial de usar a API é que o Fluig já a deixa ativada pra Empresa do usuário logado. O que também dá problemas, já que nisso não executa o método de Habilitação, só o método de Instalação (quando usando os eventos de deploy na widget).
Não! Jogando a widget diretamente na pasta /appserver/apps não é necessário ativar ela pelo painel, ela já é deployada e ativada automaticamente, o que pra automação com o git actions é perfeito, resolve exatamente o problema que eu estava!
Quando enviamos por API (ou pela Central de Componentes) o deploy é feito para todas as Empresas, porém ela só é habilitada para a Empresa do usuário logado.
Interessante que no caso de jogar direto na pasta apps já é efetuado deploy e habilitação pra todas as Empresas.
Ah sim, agora entendi o que você quis dizer, interessante isso! No meu caso, eu só trabalho em uma empresa mesmo então não iria perceber a diferença então..
Eu também só percebi quando comecei a estudar os eventos de deploy e resolvi criar mais empresas localmente pra testar.
você sabe de alguma forma de dar deploy de processos sem ser via eclipse também? estou pensando se consigo implementar isso junto ao git actions, não vejo a hora de me livrar do eclipse!
Dá uma olhada nessa extensão do VS Code:
Ah, no momento estávamos falando de widget e a palavra processo fugiu da minha atenção.
Mas, respondendo, por enquanto não tem um jeito para os processos.
Tem API pra isso, mas o problema é “empacotar” tudo no XML que é enviado.
Tem alguns colegas pesquisando isso, mas ainda nada definido.
entendi, eu consegui pelo git actions integrar corretamente as widgets, desde o empacotamento em .war até o deploy no servidor.. ficou 100% automático, agora chega de ter que empacotar e procurar o /target de cada widget por mudar 1 linha só de css.. por algum motivo não consigo exportar direto pro servidor via extensão do vscode ou do eclipse..
caso queira testar, vou deixar o yml que eu uso no meu action:
name: Deploy Automático de Widgets
on:
push:
branches:
- main
paths:
- 'Widgets/**'
jobs:
build-and-deploy:
runs-on: self-hosted
steps:
- name: 📥 Fazer o Checkout do Código
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: 🔍 Descobrir qual Widget foi alterada
id: changed-files
run: |
echo "Buscando arquivos modificados..."
# O --diff-filter=ACMR faz o Git ignorar exclusões (D - Deleted)
# Ele só pega (A)dded, (C)opied, (M)odified e (R)enamed
MODIFIED_WIDGETS=$(git diff --name-only --diff-filter=ACMR ${{ github.event.before }} ${{ github.sha }} | grep '^Widgets/' | awk -F'/' '{print $1"/"$2}' | sort -u)
# Validação extra: só adiciona na fila se a pasta realmente existir no servidor
VALID_WIDGETS=""
for WIDGET in $MODIFIED_WIDGETS; do
if [ -d "$WIDGET" ]; then
VALID_WIDGETS="$VALID_WIDGETS $WIDGET"
fi
done
# Remove espaços vazios no começo ou fim
VALID_WIDGETS=$(echo $VALID_WIDGETS | xargs)
if [ -z "$VALID_WIDGETS" ]; then
echo "Nenhuma widget existente foi alterada (provavelmente foram apenas exclusões)."
echo "run_deploy=false" >> $GITHUB_OUTPUT
exit 0
fi
echo "Widgets válidas para deploy: $VALID_WIDGETS"
echo "widgets=$VALID_WIDGETS" >> $GITHUB_OUTPUT
echo "run_deploy=true" >> $GITHUB_OUTPUT
- name: ☕ Setup do Java 8
if: steps.changed-files.outputs.run_deploy == 'true'
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '8'
- name: 🛠️ Instalar PowerShell
if: steps.changed-files.outputs.run_deploy == 'true'
run: |
sudo apt-get update
sudo apt-get install -y wget apt-transport-https software-properties-common
wget -q "https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/packages-microsoft-prod.deb"
sudo dpkg -i packages-microsoft-prod.deb
sudo apt-get update
sudo apt-get install -y powershell
- name: 📦 Empacotar Widgets
if: steps.changed-files.outputs.run_deploy == 'true'
run: |
WIDGETS="${{ steps.changed-files.outputs.widgets }}"
for WIDGET_PATH in $WIDGETS; do
echo "Empacotando: $WIDGET_PATH"
pwsh ./build-widget.ps1 -WidgetPath "./$WIDGET_PATH" -OutputDir "./target"
done
- name: ✅ Enviar para o Servidor Fluig
if: steps.changed-files.outputs.run_deploy == 'true'
run: |
echo "Enviando .war para o servidor..."
cp ./target/*.war /opt/fluig/appserver/apps/
chmod 777 /opt/fluig/appserver/apps/*.war
echo "✅ Arquivo enviado, basta aguardar o deploy automático!"
e o código pra empacotar:
<#
.SYNOPSIS
Gera arquivo .war para uma widget Fluig buscando dinamicamente a pasta src.
#>
param(
[Parameter(Mandatory=$true)]
[string]$WidgetPath,
[string]$OutputDir = "./target"
)
Write-Host "----------------------------------------------" -ForegroundColor Cyan
Write-Host "🔍 Analisando diretório: $WidgetPath" -ForegroundColor Cyan
# Busca recursivamente a pasta 'webapp' que termine com 'src/main/webapp' em qualquer nível
$webappFolder = Get-ChildItem -Path $WidgetPath -Directory -Recurse -Filter "webapp" | Where-Object { $_.FullName -match "src[\\/]main[\\/]webapp$" } | Select-Object -First 1
if (-not $webappFolder) {
Write-Host "⚠️ Nenhuma estrutura de widget (src/main/webapp) encontrada dentro de $WidgetPath. Ignorando silenciosamente." -ForegroundColor Yellow
exit 0
}
# Define os caminhos exatos achados pelo caçador
$webappDir = $webappFolder.FullName
$resourcesDir = $webappFolder.FullName.Replace("webapp", "resources")
# Descobre o nome da widget subindo 3 níveis na pasta (webapp -> main -> src -> NomeDaWidget)
$widgetRoot = $webappFolder.Parent.Parent.Parent.FullName
$widgetName = Split-Path $widgetRoot -Leaf
Write-Host "🚀 Widget localizada: ${widgetName}" -ForegroundColor Cyan
$warFile = Join-Path $OutputDir "${widgetName}.war"
if (!(Test-Path $OutputDir)) {
New-Item -ItemType Directory -Path $OutputDir -Force | Out-Null
}
if (Test-Path $warFile) { Remove-Item $warFile -Force }
try {
$zip = [System.IO.Compression.ZipFile]::Open($warFile, [System.IO.Compression.ZipArchiveMode]::Create)
$entryCount = 0
# 1. PROPERTIES
if (Test-Path $resourcesDir) {
Write-Host "📂 Empacotando properties..."
$files = Get-ChildItem $resourcesDir -Recurse -File
foreach ($file in $files) {
$rel = $file.FullName.Substring($resourcesDir.Length + 1).Replace('\', '/').Replace('//', '/')
[System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile(
$zip, $file.FullName, "WEB-INF/classes/$rel",
[System.IO.Compression.CompressionLevel]::Optimal
) | Out-Null
$entryCount++
}
}
# 2. WEBAPP
Write-Host "🌐 Empacotando arquivos web..."
$webFiles = Get-ChildItem $webappDir -Recurse -File
foreach ($file in $webFiles) {
$rel = $file.FullName.Substring($webappDir.Length + 1).Replace('\', '/').Replace('//', '/')
[System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile(
$zip, $file.FullName, $rel,
[System.IO.Compression.CompressionLevel]::Optimal
) | Out-Null
$entryCount++
}
$zip.Dispose()
$fileSize = [math]::Round((Get-Item $warFile).Length / 1KB, 1)
Write-Host "✅ SUCESSO: ${widgetName}.war gerado ($entryCount arquivos, ${fileSize} KB)" -ForegroundColor Green
}
catch {
Write-Host "❌ ERRO ao empacotar ${widgetName}: $($_.Exception.Message)" -ForegroundColor Red
if ($zip) { $zip.Dispose() }
exit 1
}
A API, que comentei, é essa: TOTVS Fluig API
No caso são os endpoints
A dificuldade que já sentimos é que o XML não é exatamente o que o Eclipse gera. Então precisa fazer uma análise nele pra descobrir como “empacotar” o processo pra exportar.