AutomationFlowsData & Sheets › Bussola Publica - Ingestao Diaria 06h (execute Command)

Bussola Publica - Ingestao Diaria 06h (execute Command)

Bussola Publica - Ingestao Diaria 06h. Uses executeCommand, postgres, emailSend. Scheduled trigger; 7 nodes.

Cron / scheduled trigger★★★★☆ complexity7 nodesExecute CommandPostgresEmail Send
Data & Sheets Trigger: Cron / scheduled Nodes: 7 Complexity: ★★★★☆ Added:

This workflow follows the Emailsend → Postgres recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "name": "Bussola Publica - Ingestao Diaria 06h",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 6 * * *"
            }
          ]
        }
      },
      "id": "a1b2c3d4-0001-4a01-9f01-000000000001",
      "name": "Agendamento 06h (diario)",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        -160,
        300
      ],
      "notes": "Dispara todo dia as 06:00 (horario do servidor n8n). Cron: 0 6 * * *"
    },
    {
      "parameters": {
        "command": "set DRY_RUN=true && cd /d \"C:\\Users\\marlon.vargas\\OneDrive\\\u00c1rea de Trabalho\\Marlon\\P\u00f3s Tech\\Desafio_Data_Challenges\" && \".venv-win\\Scripts\\python.exe\" main.py"
      },
      "id": "a1b2c3d4-0002-4a02-9f02-000000000002",
      "name": "Rodar Pipeline (main.py)",
      "type": "n8n-nodes-base.executeCommand",
      "typeVersion": 1,
      "onError": "continueRegularOutput",
      "position": [
        80,
        300
      ],
      "notes": "Executa o ponto de entrada do projeto via Poetry. Ajuste o caminho /opt/bussola-publica para a pasta real do repo no servidor. main.py roda: Etapa 2 (extracao) -> Etapa 3 (transformacao/carga) -> Etapa 4 (IA: resumo + tema em uma chamada GPT). Requer DRY_RUN=false no .env para a IA gravar de verdade. Exit != 0 em qualquer etapa dispara o Alerta de Falha."
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "loose",
            "version": 2
          },
          "conditions": [
            {
              "id": "cond-exit-0",
              "leftValue": "={{ $json.exitCode }}",
              "rightValue": 0,
              "operator": {
                "type": "number",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "a1b2c3d4-0003-4a03-9f03-000000000003",
      "name": "Pipeline OK?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        320,
        300
      ],
      "notes": "Execute Command retorna exitCode=0 quando o pipeline roda sem erro. Ramo TRUE -> digest de sucesso. Ramo FALSE -> alerta de falha."
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT\n  sigla_tipo,\n  numero,\n  ano,\n  tema,\n  resumo_executivo,\n  LEFT(ementa, 260) AS ementa_curta,\n  data_apresentacao,\n  COUNT(*) OVER () AS total_dia\nFROM fato_proposicoes\nWHERE created_at >= NOW() - INTERVAL '24 hours'\n  AND ementa IS NOT NULL AND trim(ementa) <> ''\nORDER BY (tema IS NOT NULL AND resumo_executivo IS NOT NULL) DESC,\n         data_apresentacao DESC\nLIMIT 5;",
        "options": {}
      },
      "id": "a1b2c3d4-0004-4a04-9f04-000000000004",
      "name": "Consultar Proposicoes do Dia",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.5,
      "alwaysOutputData": true,
      "position": [
        560,
        180
      ],
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      },
      "notes": "Conecta direto no Supabase/Postgres. Traz as 5 proposicoes das ultimas 24h, priorizando as que ja tem tema + resumo gerados pela IA (Etapa 4: uma chamada GPT retorna JSON com ambos)."
    },
    {
      "parameters": {
        "mode": "runOnceForAllItems",
        "language": "javaScript",
        "jsCode": "// Monta o corpo HTML do digest a partir das proposicoes retornadas pelo Postgres.\n// Obs: o no Postgres tem 'Always Output Data' ligado - com 0 linhas ele emite\n// um item vazio {}. Filtramos para nao virar linha fantasma no e-mail.\n// HONESTIDADE NO PRODUTO: se a IA nao classificou/resumiu (tema ou resumo\n// nulos no banco), o e-mail mostra isso explicitamente em vez de fingir.\nconst esc = s => String(s ?? '').replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');\nconst itens = $input.all().map(i => i.json).filter(p => p && p.sigla_tipo);\nconst total = itens.length;\nconst totalDia = itens.length > 0 ? Number(itens[0].total_dia) : 0;\nconst hoje = new Date().toLocaleDateString('pt-BR');\n\nlet linhas = itens.map(p => {\n  const titulo = `${p.sigla_tipo || ''} ${p.numero || ''}/${p.ano || ''}`.trim();\n  const temaHtml = p.tema\n    ? `<span style=\"background:#e8f0fe;color:#1a3e72;padding:2px 8px;border-radius:10px;font-size:12px;\">${esc(p.tema)}</span>`\n    : `<span style=\"background:#f1f1f1;color:#888;padding:2px 8px;border-radius:10px;font-size:12px;\">Nao classificada</span>`;\n  const resumoHtml = p.resumo_executivo\n    ? esc(p.resumo_executivo)\n    : `${esc(p.ementa_curta)} <small style=\"color:#b00020;\">(ementa original \u2014 resumo IA pendente)</small>`;\n  return `\n    <tr>\n      <td style=\"padding:8px;border-bottom:1px solid #eee;font-weight:600;\">${esc(titulo)}</td>\n      <td style=\"padding:8px;border-bottom:1px solid #eee;\">${temaHtml}</td>\n      <td style=\"padding:8px;border-bottom:1px solid #eee;color:#333;\">${resumoHtml}</td>\n    </tr>`;\n}).join('');\n\nif (total === 0) {\n  linhas = `<tr><td colspan=\"3\" style=\"padding:12px;color:#888;\">Nenhuma proposicao nova nas ultimas 24h.</td></tr>`;\n}\n\nconst html = `\n  <div style=\"font-family:Arial,Helvetica,sans-serif;max-width:680px;margin:auto;\">\n    <h2 style=\"color:#1a3e72;\">Bussola Publica \u2014 Radar Legislativo (${hoje})</h2>\n    <p style=\"color:#444;\">Pipeline executado com sucesso as 06h. <b>${totalDia}</b> proposicao(oes) nova(s) nas ultimas 24h \u2014 top <b>${total}</b> priorizadas abaixo, com tema e resumo executivo gerados por IA (GPT, uma chamada por proposicao).</p>\n    <table style=\"border-collapse:collapse;width:100%;font-size:14px;\">\n      <thead>\n        <tr style=\"background:#1a3e72;color:#fff;text-align:left;\">\n          <th style=\"padding:8px;\">Proposicao</th>\n          <th style=\"padding:8px;\">Tema (IA)</th>\n          <th style=\"padding:8px;\">Resumo executivo (IA)</th>\n        </tr>\n      </thead>\n      <tbody>${linhas}</tbody>\n    </table>\n    <p style=\"color:#999;font-size:12px;margin-top:16px;\">Gerado automaticamente pelo pipeline Bussola Publica (n8n + Supabase + OpenAI).</p>\n  </div>`;\n\nreturn [{ json: { total, totalDia, hoje, html, assunto: `Bussola Publica \u2014 ${totalDia} proposicoes novas (${hoje})` } }];\n"
      },
      "id": "a1b2c3d4-0005-4a05-9f05-000000000005",
      "name": "Montar Digest (HTML)",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        800,
        180
      ],
      "notes": "Transforma as linhas do banco em um e-mail HTML legivel. Exibe tema e resumo gerados pela IA \u2014 e sinaliza explicitamente quando a IA ainda nao processou (sem fallback disfarcado)."
    },
    {
      "parameters": {
        "fromEmail": "mssvargas07@gmail.com",
        "toEmail": "mssvargas07@gmail.com",
        "subject": "={{ $json.assunto }}",
        "emailFormat": "html",
        "html": "={{ $json.html }}",
        "options": {}
      },
      "id": "a1b2c3d4-0006-4a06-9f06-000000000006",
      "name": "Enviar Digest (Sucesso)",
      "type": "n8n-nodes-base.emailSend",
      "typeVersion": 2.1,
      "position": [
        1040,
        180
      ],
      "credentials": {
        "smtp": {
          "name": "<your credential>"
        }
      },
      "notes": "Envia o digest diario por e-mail (SMTP/Gmail). Troque o destinatario conforme o cliente."
    },
    {
      "parameters": {
        "fromEmail": "mssvargas07@gmail.com",
        "toEmail": "mssvargas07@gmail.com",
        "subject": "[FALHA] Pipeline Bussola Publica nao concluiu (06h)",
        "emailFormat": "html",
        "html": "=<div style=\"font-family:Arial,sans-serif;\"><h3 style=\"color:#b00020;\">Falha na execucao do pipeline</h3><p>O pipeline diario das 06h retornou erro (exitCode {{ $json.exitCode }}).</p><pre style=\"background:#f5f5f5;padding:10px;border-radius:6px;white-space:pre-wrap;\">{{ $json.stderr || $json.stdout }}</pre><p>Verifique os logs em /opt/bussola-publica/logs.</p></div>",
        "options": {}
      },
      "id": "a1b2c3d4-0007-4a07-9f07-000000000007",
      "name": "Alerta de Falha",
      "type": "n8n-nodes-base.emailSend",
      "typeVersion": 2.1,
      "position": [
        560,
        420
      ],
      "credentials": {
        "smtp": {
          "name": "<your credential>"
        }
      },
      "notes": "Se o pipeline falhar, avisa o time imediatamente com o stderr \u2014 automacao que nao depende da memoria do analista."
    }
  ],
  "connections": {
    "Agendamento 06h (diario)": {
      "main": [
        [
          {
            "node": "Rodar Pipeline (main.py)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Rodar Pipeline (main.py)": {
      "main": [
        [
          {
            "node": "Pipeline OK?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Pipeline OK?": {
      "main": [
        [
          {
            "node": "Consultar Proposicoes do Dia",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Alerta de Falha",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Consultar Proposicoes do Dia": {
      "main": [
        [
          {
            "node": "Montar Digest (HTML)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Montar Digest (HTML)": {
      "main": [
        [
          {
            "node": "Enviar Digest (Sucesso)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1",
    "saveManualExecutions": true,
    "timezone": "America/Sao_Paulo"
  },
  "meta": {
    "templatecredsSetupCompleted": false
  },
  "tags": [
    {
      "name": "bussola-publica"
    }
  ]
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Bussola Publica - Ingestao Diaria 06h. Uses executeCommand, postgres, emailSend. Scheduled trigger; 7 nodes.

Source: https://github.com/micaellimaj/Bussola-Publica-Pipeline-de-Inteligencia-Legislativa-com-IA/blob/main/n8n/bussola_publica_ingestao_diaria_WINDOWS.json — original creator credit. Request a take-down →

More Data & Sheets workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Data & Sheets

Bussola Publica - Ingestao Diaria 06h. Uses executeCommand, postgres, emailSend. Scheduled trigger; 7 nodes.

Execute Command, Postgres, Email Send
Data & Sheets

Disparador 1.8. Uses itemLists, postgres, emailSend, httpRequest. Scheduled trigger; 85 nodes.

Item Lists, Postgres, Email Send +1
Data & Sheets

Automated Knowledge Management Backup & Recovery. Uses executeCommand, postgres, httpRequest, googleDrive. Scheduled trigger; 30 nodes.

Execute Command, Postgres, HTTP Request +1
Data & Sheets

This n8n workflow runs daily to analyze active customer behavior, engineers relevant features from usage and transaction data, applies a machine learning or AI-based model to predict churn probability

HTTP Request, Postgres, Email Send
Data & Sheets

This n8n workflow automates continuous compliance monitoring across IT, OT, and cloud environments by aggregating security controls, validating policies (ISO 27001, NIST, GDPR, SOC2), detecting anomal

HTTP Request, Postgres, Email Send