Skip to content

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

Merged
dpaes merged 3 commits into
developfrom
danilocarneiro/evo-1571-historicotracking-fix-end-to-end-do-fluxo-de-eventos-do
Jun 1, 2026
Merged

chore(docker): stack local evo-flow + clickhouse para tracking de eventos (EVO-1571)#114
dpaes merged 3 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.

PR #114 should only ship the local evo-flow docker stack
(docker-compose.evoflow.yaml + .env.example). The submodule pointer
bumps did not belong here:

- evo-ai-frontend-community 58305bc -> 306e974: 58305bc is an orphan
  from a rebase of #116 (real head d0e6d52), not in any remote branch.
- evo-ai-crm-community 509ac56 -> 48c9e93: 509ac56 is EVO-1570 WIP
  (reporting-event mapping), not on develop.

Umbrella submodule pointers belong in a batched chore(submodules),
not in a feature PR. Restored both gitlinks to their develop values.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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 3 (EVO-1571 · local evo-flow docker stack) — approved ✅

Re-reviewed against origin/develop (8d31ecb) and the current head (28a3248). Both prior blockers are resolved.

✅ Round-2 blocker (broken submodule gitlinks): resolved

Commit 28a3248 drops the two gitlink bumps (evo-ai-frontend 58305bc, evo-ai-crm 509ac56) and restores both pointers to their develop values. The PR now touches only 2 filesdocker-compose.evoflow.yaml (new) and .env.example — with no gitlink diff. This is exactly the requested change: umbrella submodule pointers belong in a batched chore(submodules), not a feature PR.

✅ Round-1 blocker (fresh-clone build): holds on develop

Verified on origin/develop: .gitignore ignores evo-flow/, .gitmodules has the evo-flow entry commented out, and there is no evo-flow gitlink in the tree. The compose header documents the git clone … ./evo-flow prerequisite. A fresh clone + the documented up command works.

✅ Compose wiring

Checked against the main docker-compose.yml: postgres (with a pg_isready healthcheck), evo-crm, and evo-auth all exist, so depends_on: { postgres: service_healthy } and the hostnames evo-crm:3000 / evo-auth:3001 resolve. Postgres credential defaults match (POSTGRES_USERNAME:-postgres / POSTGRES_PASSWORD:-evoai_dev_password). AC#6 met.

🟡 Non-blocking (Sourcery also flagged this)

The inline command: uses a node -e one-liner for CREATE DATABASE and runs typeorm migration:run … || echo "failed (continuing)", which swallows a migration failure (the container can start with an incomplete schema). Acceptable for a dev-only override that is validated end-to-end per the card's validation steps. Optional hardening: move the bootstrap to a small script and let migration failures fail fast. Minor: clickhouse/clickhouse-server:latest is unpinned; dev-default secrets are committed (overridable). None blocking.

🧵 Note (out of this PR's scope)

End-to-end in the umbrella still requires a batched chore(submodules) bumping the CRM (#106, already on develop) and FE (#116 post-merge SHA) pointers. This PR correctly does not do that. Approving.

@dpaes dpaes merged commit ac26b89 into develop Jun 1, 2026
3 checks passed
@dpaes dpaes deleted the danilocarneiro/evo-1571-historicotracking-fix-end-to-end-do-fluxo-de-eventos-do branch June 1, 2026 13:02
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