Consolida os dois controladores legados que decidiam status/fechamento de forma concorrente (processGlpiClosureController + processStatusController) em um único processTicketLifecycleController, eliminando a dependência do campo source_last (mantido só como rastro de auditoria) e a flag ENABLE_STATUS_SYNC (removida). Isso corrige o bug de reabertura: chamados reabertos no SN voltavam a ser fechados no GLPI porque a regra de precedência de finalização do fluxo legado forçava o status do GLPI de volta pro SN. Correções de bugs encontrados em teste (Frente 1): - Constraint UNIQUE em ticket_sync.sn_ticket_id + ON CONFLICT DO NOTHING na criação do registro, prevenindo duplicação de tickets. - Fechamento no SN agora é confirmado por leitura ao vivo do status antes de marcar o ticket como solved/closed, em vez de confiar só no HTTP 200 (a API do SN pode retornar sucesso e silenciosamente ignorar um valor de estado inválido — descoberto e corrigido também no mandante). - Nota de encerramento do SN pro GLPI agora é idempotente e criada uma única vez por ticket. - Erros de sincronização passam a ter um limite de tentativas (MAX_ERROR_RETRIES) antes de marcar o ticket como error_permanent, exigindo intervenção manual em vez de tentar para sempre. - Chamados criados no GLPI passam a gravar o número do ticket do SN no campo externalid. Nova funcionalidade (Frente 2): quando o SN resolve/encerra um chamado por conta própria antes do GLPI, além da nota informativa no GLPI (agora com o nome de quem encerrou, buscado ao vivo via resolved_by/closed_by/ sys_updated_by), o próprio SN recebe um aviso de que a Sothis não vai mais atender aquele chamado e ele é transferido pra fila de TI da CAOA. Nova funcionalidade (Mandante, regras 19-22): espelhamento opcional e configurável de status intermediário (Aguardando Atendimento/Em Atendimento/Em Espera) entre os dois sistemas, controlado pela env MANDANTE=GLPI|SNOW. Sem essa env configurada, mantém o comportamento atual (nenhum espelhamento de status intermediário). Nunca afeta os status finais (resolvido/encerrado/fora de escopo), que continuam regidos pelas regras fixas de fechamento. Corrigido também o workflow de deploy (.gitea/workflows/deploy-production.yml), que ainda validava os controladores antigos (já removidos) e exigia ENABLE_STATUS_SYNC=true, o que quebraria o próximo deploy em produção. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
94 lines
2.4 KiB
YAML
94 lines
2.4 KiB
YAML
name: Deploy production
|
|
|
|
on:
|
|
push:
|
|
branches:
|
|
- master
|
|
workflow_dispatch:
|
|
|
|
jobs:
|
|
deploy:
|
|
name: Deploy to production VM
|
|
runs-on: vm-prod
|
|
env:
|
|
PROD_DEPLOY_PATH: ${{ vars.PROD_DEPLOY_PATH }}
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Preflight
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
echo "Runner: $(hostname)"
|
|
node --version
|
|
npm --version
|
|
pm2 --version
|
|
rsync --version | head -n 1
|
|
|
|
- name: Validate JavaScript
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
node --check cron.js
|
|
node --check src/app.js
|
|
node --check src/controllers/processTicketLifecycleController.js
|
|
node --check src/services/servicenowService.js
|
|
node --check src/services/glpiTicketService.js
|
|
|
|
- name: Deploy files and restart PM2
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
|
|
DEPLOY_PATH="${PROD_DEPLOY_PATH:-/opt/sn-glpi-sync-new}"
|
|
LOCK_FILE="/tmp/sn-glpi-sync-new.deploy.lock"
|
|
|
|
mkdir -p "$DEPLOY_PATH"
|
|
|
|
(
|
|
flock -n 9 || {
|
|
echo "Another deploy is already running."
|
|
exit 1
|
|
}
|
|
|
|
rsync -az --delete \
|
|
--exclude='.git/' \
|
|
--exclude='.gitea/' \
|
|
--exclude='.env*' \
|
|
--exclude='node_modules/' \
|
|
--exclude='logs/' \
|
|
./ "$DEPLOY_PATH"/
|
|
|
|
cd "$DEPLOY_PATH"
|
|
|
|
test -f .env.production || {
|
|
echo "Missing $DEPLOY_PATH/.env.production"
|
|
exit 1
|
|
}
|
|
|
|
grep -q '^SERVICENOW_CAOA_TI_GROUP_ID=.\+' .env.production || {
|
|
echo "SERVICENOW_CAOA_TI_GROUP_ID must be set in $DEPLOY_PATH/.env.production"
|
|
exit 1
|
|
}
|
|
|
|
npm ci --omit=dev
|
|
|
|
node --check cron.js
|
|
node --check src/app.js
|
|
node --check src/controllers/processTicketLifecycleController.js
|
|
node --check src/services/servicenowService.js
|
|
node --check src/services/glpiTicketService.js
|
|
|
|
pm2 startOrRestart ecosystem.config.js --env production
|
|
pm2 save
|
|
pm2 list
|
|
) 9>"$LOCK_FILE"
|
|
|
|
- name: Show sync logs
|
|
if: always()
|
|
shell: bash
|
|
run: |
|
|
pm2 logs sn-glpi-sync-cron --nostream --lines 80 || true
|