Skip to content

chore(docker): stack local evo-flow + clickhouse para tracking de eventos (EVO-1571)#114

Open
daniloleonecarneiro wants to merge 2 commits into
developfrom
danilocarneiro/evo-1571-historicotracking-fix-end-to-end-do-fluxo-de-eventos-do
Open

chore(docker): stack local evo-flow + clickhouse para tracking de eventos (EVO-1571)#114
daniloleonecarneiro wants to merge 2 commits into
developfrom
danilocarneiro/evo-1571-historicotracking-fix-end-to-end-do-fluxo-de-eventos-do

Conversation

@daniloleonecarneiro
Copy link
Copy Markdown
Contributor

@daniloleonecarneiro daniloleonecarneiro commented May 29, 2026

Summary

Adiciona o setup local que faz o fluxo de Histórico/Tracking rodar end-to-end (complementa os PRs de código: evo-flow direct, proxy 7.7, UI traits 7.8).

  • docker-compose.evoflow.yaml (novo) — override sobre o docker-compose.yml principal que sobe clickhouse + a app evo-flow (RUN_MODE=api + QUEUE_MODE=direct + WRITE_MODE=ch-sync) na rede default do projeto, então o evo-crm alcança http://evo-flow:3334. O evo-flow auto-cria o DB Postgres dedicado evo_campaign + roda migrations no start (não há db:create oficial; o evo_community do CRM não serve — colide com tabelas do Chatwoot).
  • .env.example — documenta EVO_FLOW_ENABLED, EVO_FLOW_API_URL, AUTH_APIKEY_INTEGRATION_LOCAL, EVO_FLOW_ALLOW_INSECURE.

Por que

Sem isso, o evo-flow não está em nenhum compose (o docker-compose.flow.yaml é só infra Kafka/Temporal, em rede isolada, e não sobe a app), e os listeners do CRM viram no-op sem as vars — a aba "Eventos" do contato não funciona.

Como subir

docker compose -f docker-compose.yml -f docker-compose.evoflow.yaml up -d

(ou COMPOSE_FILE=docker-compose.yml:docker-compose.evoflow.yaml no .env para docker compose up direto)

Test plan

  • Subir o stack, logar no FE, editar um contato → aba Eventos mostra o contact.updated.
  • docker exec ... clickhouse-client -q "SELECT count() FROM evo_campaign.contact_events" cresce a cada edição.

Notas

  • QUEUE_MODE=direct depende do PR do evo-flow (DirectQueueProcessor) — buildar a imagem do evo-flow a partir dessa branch.
  • Não inclui mudanças de submódulo/Makefile (fora de escopo).

Relacionado: EVO-1571

Summary by Sourcery

New Features:

  • Introduce a docker-compose.evoflow.yaml stack that brings up evo-flow and ClickHouse on the same network as the main evo-crm services.

Summary by Sourcery

New Features:

  • Introduce docker-compose.evoflow.yaml to spin up evo-flow and ClickHouse on the same network as the primary evo-crm stack for local event tracking.

…ntos (EVO-1571)

Adiciona docker-compose.evoflow.yaml (override sobre o docker-compose.yml principal) que sobe clickhouse + a app evo-flow (RUN_MODE=api + QUEUE_MODE=direct + WRITE_MODE=ch-sync) na rede default do projeto, integrado ao CRM. O evo-flow auto-cria o DB Postgres dedicado evo_campaign + roda migrations no start (sem db:create oficial). Documenta as vars no .env.example (EVO_FLOW_ENABLED, EVO_FLOW_API_URL, AUTH_APIKEY_INTEGRATION_LOCAL, EVO_FLOW_ALLOW_INSECURE). Subir: docker compose -f docker-compose.yml -f docker-compose.evoflow.yaml up -d.
@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented May 29, 2026

Reviewer's Guide

Adds a new docker-compose override to run evo-flow and ClickHouse in the main evo-crm docker stack, wiring env vars and bootstrap commands so the local event tracking flow works end-to-end.

Sequence diagram for local contact event tracking with evo-flow and ClickHouse

sequenceDiagram
  actor User
  participant EvoCRM as Evo_CRM_FE+API
  participant EvoFlow as Evo_Flow_API
  participant ClickHouse

  User->>EvoCRM: Update contact
  EvoCRM->>EvoFlow: POST /events (AUTH_APIKEY_INTEGRATION_LOCAL)
  EvoFlow->>ClickHouse: INSERT INTO contact_events (WRITE_MODE=ch-sync)
  ClickHouse-->>EvoFlow: insert ok
  EvoFlow-->>EvoCRM: 200 OK
  User->>EvoCRM: Open contact Events tab
  EvoCRM->>EvoFlow: GET /contacts/:id/events
  EvoFlow->>ClickHouse: SELECT * FROM contact_events
  ClickHouse-->>EvoFlow: rows
  EvoFlow-->>EvoCRM: events
  EvoCRM-->>User: Render contact.updated events
Loading

Flow diagram for evo-flow container bootstrap with dedicated Postgres DB

flowchart TD
  A[Evo-flow container start] --> B[Node pg Client connects
to Postgres database=postgres]
  B --> C[CREATE DATABASE evo_campaign]
  C --> D[If exists
log db already exists]
  D --> E[Run typeorm migration:run
-d dist/database/ormconfig.js]
  E --> F[exec node dist/main.js
RUN_MODE=api
QUEUE_MODE=direct
WRITE_MODE=ch-sync]
Loading

File-Level Changes

Change Details Files
Introduce docker-compose override stack that adds ClickHouse and evo-flow wired to existing postgres and auth/CRM services so local event tracking works end-to-end.
  • Add clickhouse service with persistent volume, healthcheck, and default credentials exposed on standard ports
  • Add evo-flow service built from local ./evo-flow Dockerfile, exposing port 3334 on the default project network
  • Wire evo-flow environment for minimal stack (RUN_MODE=api, QUEUE_MODE=direct, WRITE_MODE=ch-sync, STORAGE_MODE=clickhouse) and integrate with auth, ClickHouse, postgres, and CRM HTTP API
  • Add custom container command that idempotently creates the dedicated evo_campaign Postgres database, runs TypeORM migrations, and then starts the app, depending on clickhouse and postgres health
docker-compose.evoflow.yaml

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="docker-compose.evoflow.yaml" line_range="52-53" />
<code_context>
+      - sh
+      - -c
+      - |
+        node -e 'const{Client}=require("pg");const db=process.env.POSTGRES_DB_DATABASE;const c=new Client({host:process.env.POSTGRES_DB_HOST,port:+(process.env.POSTGRES_DB_PORT||5432),user:process.env.POSTGRES_DB_USERNAME,password:process.env.POSTGRES_DB_PASSWORD,database:"postgres"});c.connect().then(()=>c.query("CREATE DATABASE "+db)).then(()=>console.log("[init] created "+db)).catch(e=>console.log("[init] "+(e.code==="42P04"?"db already exists":e.message))).finally(()=>c.end());'
+        node_modules/.bin/typeorm migration:run -d dist/database/ormconfig.js || echo "[init] migration:run failed (continuing)"
+        exec node dist/main.js
+    environment:
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Inline Node DB bootstrap script is hard to maintain and lacks failure signaling.

The `node -e` database creation command is difficult to read, test, and debug, and `migration:run` failures are deliberately ignored, so the container can appear healthy with an incomplete schema. Consider moving this logic into a dedicated JS/TS bootstrap file in the repo and calling it here, and decide whether migration failures should instead cause the container to exit so misconfigurations fail fast.

Suggested implementation:

```
    # Recorrência: o banco Postgres do evo-flow é DEDICADO (evo_campaign) — NÃO
    # compartilha o evo_community do CRM (as migrations do evo-flow criam tabelas
    # contacts/labels/custom_attribute_definitions que colidiriam com o Chatwoot;
    # o evo-flow lê o CRM via HTTP, não via Postgres). Como o evo-flow não tem
    # passo oficial de db:create, o script bootstrap cuida de:
    # - criar o DB se faltar
    # - rodar as migrations (idempotente)
    # - subir a app
    # Se as migrations falharem, o container sai com erro para que a má
    # configuração seja detectada rapidamente.
    command:
      - sh
      - -c
      - |
        set -e
        node dist/bootstrap.js

```

```
      CLICKHOUSE_PASSWORD: password
      CLICKHOUSE_DB: default

```

To fully implement your suggestion, the repository also needs a dedicated bootstrap script (e.g. `src/bootstrap.ts` compiled to `dist/bootstrap.js`) that encapsulates the previous inline behavior and exits non-zero on migration failure. For example, it should:
1. Use `pg` to connect to the Postgres server, create the target database if it does not exist, and log informative messages.
2. Run `typeorm migration:run -d dist/database/ormconfig.js` (via `child_process.spawn`/`exec`) and propagate any non-zero exit code.
3. Start the application (e.g. `require('./main');` or `import('./main');`) only if the above steps succeed.
Also ensure the Docker build produces `dist/bootstrap.js` and that the working directory in the container is where `dist/` is located so `node dist/bootstrap.js` resolves correctly.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +52 to +53
node -e 'const{Client}=require("pg");const db=process.env.POSTGRES_DB_DATABASE;const c=new Client({host:process.env.POSTGRES_DB_HOST,port:+(process.env.POSTGRES_DB_PORT||5432),user:process.env.POSTGRES_DB_USERNAME,password:process.env.POSTGRES_DB_PASSWORD,database:"postgres"});c.connect().then(()=>c.query("CREATE DATABASE "+db)).then(()=>console.log("[init] created "+db)).catch(e=>console.log("[init] "+(e.code==="42P04"?"db already exists":e.message))).finally(()=>c.end());'
node_modules/.bin/typeorm migration:run -d dist/database/ormconfig.js || echo "[init] migration:run failed (continuing)"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (bug_risk): Inline Node DB bootstrap script is hard to maintain and lacks failure signaling.

The node -e database creation command is difficult to read, test, and debug, and migration:run failures are deliberately ignored, so the container can appear healthy with an incomplete schema. Consider moving this logic into a dedicated JS/TS bootstrap file in the repo and calling it here, and decide whether migration failures should instead cause the container to exit so misconfigurations fail fast.

Suggested implementation:

    # Recorrência: o banco Postgres do evo-flow é DEDICADO (evo_campaign) — NÃO
    # compartilha o evo_community do CRM (as migrations do evo-flow criam tabelas
    # contacts/labels/custom_attribute_definitions que colidiriam com o Chatwoot;
    # o evo-flow lê o CRM via HTTP, não via Postgres). Como o evo-flow não tem
    # passo oficial de db:create, o script bootstrap cuida de:
    # - criar o DB se faltar
    # - rodar as migrations (idempotente)
    # - subir a app
    # Se as migrations falharem, o container sai com erro para que a má
    # configuração seja detectada rapidamente.
    command:
      - sh
      - -c
      - |
        set -e
        node dist/bootstrap.js

      CLICKHOUSE_PASSWORD: password
      CLICKHOUSE_DB: default

To fully implement your suggestion, the repository also needs a dedicated bootstrap script (e.g. src/bootstrap.ts compiled to dist/bootstrap.js) that encapsulates the previous inline behavior and exits non-zero on migration failure. For example, it should:

  1. Use pg to connect to the Postgres server, create the target database if it does not exist, and log informative messages.
  2. Run typeorm migration:run -d dist/database/ormconfig.js (via child_process.spawn/exec) and propagate any non-zero exit code.
  3. Start the application (e.g. require('./main'); or import('./main');) only if the above steps succeed.
    Also ensure the Docker build produces dist/bootstrap.js and that the working directory in the container is where dist/ is located so node dist/bootstrap.js resolves correctly.

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've reviewed your changes and they look great!


Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Copy link
Copy Markdown

@dpaes dpaes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review (EVO-1571 · local evo-flow stack) — change requested

The intent here is great and the wiring is mostly right, but the stack can't be brought up from a clean checkout as documented.

🔴 Blocker — build: context: ./evo-flow points at a path that isn't in the repo

docker-compose.evoflow.yaml builds the evo-flow service from ./evo-flow, but evo-flow is no longer part of this umbrella: it's commented out in .gitmodules and there is no evo-flow tree on this branch (nor on develop). It was removed as a submodule in the rc4/rc5 cleanup.

Result: a fresh clone running the documented command

docker compose -f docker-compose.yml -f docker-compose.evoflow.yaml up -d

fails with unable to prepare context: path "./evo-flow" not found. It works on your machine only because you still have a local ./evo-flow from when it was a submodule.

AC#6 ("documented how to bring it up") isn't satisfiable on a clean checkout yet. Options:

  1. Reference a published image (image: ...) instead of a local build context; or
  2. Document an explicit git clone https://github.com/evolution-foundation/evo-flow ./evo-flow step (and gitignore the dir); or
  3. Re-add evo-flow as a submodule (note: this contradicts the rc4/rc5 removal decision).

🟡 Note — submodule pointers (merge process, not a defect)

This PR doesn't bump the evo-ai-crm-community / evo-ai-frontend-community pointers, so even once ./evo-flow is resolved, the umbrella builds CRM/FE from their old commits — without the proxy fix (#106) and traits/CSP changes (#116) — until the pointers are bumped after those merge.

🟢 Minor — dev-default credentials committed

EVOAI_CRM_API_TOKEN (a fixed UUID default), AUTH_APIKEY_INTEGRATION_LOCAL=evoflow-dev-key, and the ClickHouse password are committed in the compose. They're local-only and overridable, so acceptable — just flagging for awareness.

✅ Confirmed correct

  • Service hostnames (postgres, evo-auth:3001, evo-crm:3000) match the main docker-compose.yml.
  • Dedicated evo_campaign DB rationale (avoiding the Chatwoot evo_community table collision) is sound.
  • The idempotent CREATE DATABASE + migration:run one-liner is fine.
  • .env.example documentation is clear.

daniloleonecarneiro pushed a commit that referenced this pull request May 29, 2026
… pointers (EVO-1571)

- docker-compose.evoflow.yaml: document the `git clone ... ./evo-flow`
  prerequisite. evo-flow is no longer a submodule (removed in rc4/rc5) and
  ./evo-flow is gitignored, so on a fresh clone the `build: context:
  ./evo-flow` path is missing and the documented "up" command failed.
- bump evo-ai-frontend-community -> 58305bc (EVO-1571 #116 + review fixes:
  i18n traits/noData + aria-controls test).
- bump evo-ai-crm-community -> 509ac56 (includes #106 "proxy le eventos do
  envelope data.events"), so the umbrella stops building CRM/FE from
  pre-#106/#116 commits.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… pointers (EVO-1571)

- docker-compose.evoflow.yaml: document the `git clone ... ./evo-flow`
  prerequisite. evo-flow is no longer a submodule (removed in rc4/rc5) and
  ./evo-flow is gitignored, so on a fresh clone the `build: context:
  ./evo-flow` path is missing and the documented "up" command failed.
- bump evo-ai-frontend-community -> 58305bc (EVO-1571 #116 + review fixes:
  i18n traits/noData + aria-controls test).
@daniloleonecarneiro daniloleonecarneiro force-pushed the danilocarneiro/evo-1571-historicotracking-fix-end-to-end-do-fluxo-de-eventos-do branch from afa7813 to e59af7d Compare May 29, 2026 18:50
@daniloleonecarneiro daniloleonecarneiro requested a review from dpaes May 29, 2026 19:09
Copy link
Copy Markdown

@dpaes dpaes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Re-review (round 2) — Request changes

Thanks for the rework. The fresh-clone build blocker is resolved ✅ — .gitignore now has evo-flow/, .gitmodules keeps evo-flow commented out, and docker-compose.evoflow.yaml documents the git clone … ./evo-flow prerequisite. That one is closed.

The round-2 changes introduced one new blocker: the two submodule pointer bumps are broken.

  • evo-ai-frontend-community58305bc (hard break): this commit exists on no remote branch — it's an orphan from a rebase of #116 (whose real head is d0e6d52f…; 58305bc isn't even an ancestor of it). After merging this PR, git submodule update --init on a fresh umbrella clone fails on evo-ai-frontend-community because the recorded commit can't be fetched.
  • evo-ai-crm-community509ac56 (wrong commit): not on develop — it lives on the EVO-1570 branch (refactor: unify reporting-event mapping), so it would pull another card's unmerged WIP into the umbrella. The #106 fix is already on develop as 13348b9 (current develop HEAD is dc142a4).

Requested change — remove both gitlink bumps from this PR (don't re-point them). There is no correct FE SHA to target: #116 is still open and a squash-merge produces a new develop SHA, so any value committed now is wrong by construction. Umbrella pointers are bumped in a batched chore(submodules), not in a feature PR. Keep this PR scoped to docker-compose.evoflow.yaml + .env.example (+ the .gitignore/.gitmodules changes, already good) and drop the two submodule pointer changes → then it's good to merge.

Holding the PR open for the rework.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants