Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
f702dba
New common test package. Initially contains helper methods to walk up…
pfcoperez Apr 14, 2026
1ae4106
Load `.env` from project using new walk-up tooling.
pfcoperez Apr 14, 2026
522f9f0
Update Tiltfile, `env -f` is not longer needed to pass connection or …
pfcoperez Apr 14, 2026
aeac21d
Make connectors tests load env file automatically
pfcoperez Apr 14, 2026
8e1b879
Update docs
pfcoperez Apr 14, 2026
bda3a5e
Add connectors test launchers to Tilt
pfcoperez Apr 14, 2026
e1db8b1
Add switchboard and flow e2e tests to Tiltfile
pfcoperez Apr 14, 2026
3de2679
Add Tilt buttons to clean-up Go caches, removes cleaning the cache by…
pfcoperez Apr 14, 2026
2e691e2
Make of "Start all test resources" a resource so we can invoke it fro…
pfcoperez Apr 14, 2026
a32e948
Fix linting issues
pfcoperez Apr 14, 2026
ec5fb5b
PR Comments [Tiltfile]: Fix mongo connector test references and remov…
pfcoperez Apr 15, 2026
a54dad5
Tiltfile: Provide all MySQL flavors for all tests, simplify this by f…
pfcoperez Apr 15, 2026
a22ea3e
MySQL api tests need PSQL
pfcoperez Apr 15, 2026
05767c1
PR Comments [Tiltfile]: Wrong switchboard MongoDB target
pfcoperez Apr 15, 2026
fb162a9
LoadEnv only runs on its first call
pfcoperez Apr 15, 2026
610d3e2
PR Comments [Tiltfile]: Use `-count=1` go test parameter to force at …
pfcoperez Apr 15, 2026
5a51227
PR Comments [Tiltfile]: Improve UX by sorting groups making use of Ti…
pfcoperez Apr 15, 2026
795a41f
Forced timezone with `godotenv`.
pfcoperez Apr 15, 2026
4c545a0
PR Comments [Tiltfile]: Allow parallel test execution up to 10
pfcoperez Apr 15, 2026
3fe8ae6
Fix test isolation: reset loadedEnv before each LoadEnv() call
pfcoperez Apr 15, 2026
497aeae
Fix linting issues
pfcoperez Apr 15, 2026
4747c23
Update all resources filters.
pfcoperez Apr 16, 2026
c0b218b
Replace atomic.Bool with sync.Once in LoadEnv
github-actions[bot] Apr 16, 2026
3e9e910
Merge remote-tracking branch 'upstream/main' into DBI-640/local-dev-e…
pfcoperez Apr 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@ CI_MYSQL_GTID_PORT=3306
CI_MYSQL_POS_PORT=3307
CI_MARIADB_PORT=3308
CI_MYSQL_ROOT_PASSWORD=cipass
CI_MYSQL_VERSION=mysql-gtid
CI_MYSQL_GTID_VERSION=mysql-gtid
CI_MYSQL_POS_VERSION=mysql-pos
CI_MARIADB_VERSION=maria

CI_MYSQL_VERSION=mysql-gtid
CI_MYSQL_PORT=3306 # Default is gtid

PG_HOST=host.docker.internal
Expand All @@ -39,4 +42,6 @@ AWS_ENDPOINT_URL_S3=http://host.docker.internal:9001
AWS_EC2_METADATA_DISABLED="true"

MINIO_ROOT_USER=_peerdb_minioadmin
MINIO_ROOT_PASSWORD=_peerdb_minioadmin
MINIO_ROOT_PASSWORD=_peerdb_minioadmin

TZ='UTC'
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ For example:
```bash
cd flow
go clean -cache
env -f ../.env go test -v -run TestGenericCH_MySQL ./e2e/
go test -v -run TestGenericCH_MySQL ./e2e/
```

Or local debugging sessions.
Expand All @@ -111,6 +111,8 @@ This is done through [Tilt](https://tilt.dev/) orchestrated Docker compose.

To get the environment up you first need to specify the shared environment variables for both the test and the test environment in your local `.env` file. You can use the provided `.env.example` as a template: `cp .env.example .env `.

If a `.env` file is present in the project root, tests will automatically load it. Any variable defined in `.env` can be overridden by user-provided environment variables.

:memo: In the template, services URLs are set to `host.docker.internal`, which is the name for the default Docker gateway in Docker Desktop set-ups such as macOS and Windows. Using the default gateway address allows both test processes and services running inside Docker to access services on the host machine. In native Docker (Linux) this name is not resolved by default, you might replace it with the default gateway IP (e.g., `172.18.0.1`) or add a custom entry to your `/etc/hosts` file to resolve `host.docker.internal` to the appropriate IP address. e.g:

```bash
Expand All @@ -127,10 +129,10 @@ And follow the status of the services and access logs through the Tilt UI at htt

<img width="1593" height="693" alt="image" src="https://github.com/user-attachments/assets/6c294dda-ca8f-45cc-b75c-11594118a641" />

Since `.env` is the environment configuration source of truth, it can be used directly to inject the required variables to the test execution processes. e.g:
Since `.env` is the environment configuration source of truth, tests automatically pick it up from the project root. For example:

```bash
go clean -cache; env -f ../.env go test -v -run TestGenericCH_MySQL ./e2e/ # Some MySQL generic tests
go clean -cache; go test -v -run TestGenericCH_MySQL ./e2e/ # Some MySQL generic tests
```

### Running tests from Tilt
Expand Down
125 changes: 106 additions & 19 deletions Tiltfile
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
update_settings(max_parallel_updates=10)

allow_k8s_contexts(k8s_context()) # to unblock local() in local set-ups with a Kubernetes context configured, like Docker Desktop

docker_compose('./docker-compose-dev.yml')
Expand Down Expand Up @@ -72,42 +74,42 @@ dc_resource('minio', labels=['PeerDB'])
local_resource(
'provision-mongodb',
cmd='./local_provision_scripts/mongodb.sh',
labels=['Provisioning'],
labels=['Ancillary-DB-Provisioning'],
resource_deps=['mongodb']
)

local_resource(
'provision-clickhouse',
cmd='./local_provision_scripts/clickhouse.sh',
labels=['Provisioning'],
labels=['Ancillary-DB-Provisioning'],
resource_deps=['clickhouse']
)

local_resource(
'provision-mysql-gtid',
cmd='./local_provision_scripts/mysql.sh peerdb-mysql-gtid',
labels=['Provisioning'],
labels=['Ancillary-DB-Provisioning'],
resource_deps=['mysql-gtid']
)

local_resource(
'provision-mysql-pos',
cmd='./local_provision_scripts/mysql.sh peerdb-mysql-pos',
labels=['Provisioning'],
labels=['Ancillary-DB-Provisioning'],
resource_deps=['mysql-pos']
)

local_resource(
'provision-mariadb',
cmd='./local_provision_scripts/mysql.sh peerdb-mariadb',
labels=['Provisioning'],
labels=['Ancillary-DB-Provisioning'],
resource_deps=['mariadb']
)

local_resource(
'provision-postgres',
cmd='./local_provision_scripts/postgres.sh',
labels=['Provisioning'],
labels=['Ancillary-DB-Provisioning'],
resource_deps=['postgres']
)

Expand All @@ -123,31 +125,43 @@ docker_compose('./ancillary-docker-compose.yml', env_file=tiltfile_dir + '/ancil
# of their corresponding datastore.
# This way, users can choose which ones to start and when, depending on the tests they want to run.

dc_resource('clickhouse', labels=['DataStore'], links=[
dc_resource('clickhouse', labels=['Ancillary-DB'], links=[
link('http://localhost:11123', 'ClickHouse HTTP'),
link('http://localhost:11000', 'ClickHouse TCP'),
], auto_init=False)

dc_resource('mongodb', labels=['DataStore'], links=[
dc_resource('mongodb', labels=['Ancillary-DB'], links=[
link('http://localhost:11017', 'MongoDB'),
], auto_init=False)

dc_resource('mysql-gtid', labels=['DataStore'], links=[
dc_resource('mysql-gtid', labels=['Ancillary-DB'], links=[
link('http://localhost:3306', 'MySQL GTID'),
], auto_init=False)

dc_resource('mysql-pos', labels=['DataStore'], links=[
dc_resource('mysql-pos', labels=['Ancillary-DB'], links=[
link('http://localhost:3307', 'MySQL File-Pos'),
], auto_init=False)

dc_resource('mariadb', labels=['DataStore'], links=[
dc_resource('mariadb', labels=['Ancillary-DB'], links=[
link('http://localhost:3308', 'MariaDB'),
], auto_init=False)

dc_resource('postgres', labels=['DataStore'], links=[
dc_resource('postgres', labels=['Ancillary-DB'], links=[
link('http://localhost:5432', 'PostgreSQL'),
], auto_init=False)

local_resource(
'all-test-resources',
cmd=' '.join([
"resources=$(tilt --port 10352 get uiresource -o json |",
"jq -r '.items[] | select(.metadata.labels[\"Ancillary-DB\"] or .metadata.labels[\"Ancillary-TestInfra\"]) | .metadata.name');",
"tilt --port 10352 enable $resources &&",
"for r in $resources; do tilt --port 10352 trigger $r; done",
]),
labels=['Ancillary-Utilities'],
auto_init=False,
)

# Monitoring and utility tools

dc_resource('dozzle', labels=['Monitoring'], links=[
Expand All @@ -156,8 +170,8 @@ dc_resource('dozzle', labels=['Monitoring'], links=[

# Test services: Services supporting test execution that are not data stores, like proxies, mock servers, etc.

dc_resource('toxiproxy', labels=['TestInfra'], auto_init=False)
dc_resource('openssh', labels=['TestInfra'], auto_init=False)
dc_resource('toxiproxy', labels=['Ancillary-TestInfra'], auto_init=False)
dc_resource('openssh', labels=['Ancillary-TestInfra'], auto_init=False)

# Cleanup

Expand All @@ -173,7 +187,16 @@ cmd_button(
])],
text='Wipe ancillary volumes',
icon_name='delete',
location=location.NAV,
location=location.NAV
)

cmd_button(
'Clean-up test code caches',
Comment thread
pfcoperez marked this conversation as resolved.
argv=['sh', '-c', 'cd flow && go clean -cache'],
text='Clean-up test code caches',
icon_name='delete_sweep',
resource='Test',
location=location.NAV
)

# Tests launchers
Expand All @@ -182,29 +205,93 @@ def e2e_test(name, test_run, extra_deps=[], vars_overrides={}):
overrides_str = ' '.join(['%s=%s' % (var, value) for var, value in vars_overrides.items()])
local_resource(
'e2e_' + name,
cmd='cd flow && go clean -cache && env -f ../.env %s go test -v -run %s ./e2e/' % (overrides_str, test_run),
cmd='cd flow && %s go test -count=1 -v -run %s ./e2e/' % (overrides_str, test_run),
labels=['Test'],
auto_init=False,
Comment thread
pfcoperez marked this conversation as resolved.
resource_deps=['flow-api', 'flow-worker', 'catalog', 'provision-clickhouse'] + extra_deps,
allow_parallel=True,
)

def connector_test(connector, extra_deps=[], vars_overrides={}):
overrides_str = ' '.join(['%s=%s' % (var, value) for var, value in vars_overrides.items()])
local_resource(
'connector_' + connector,
cmd='cd flow && %s go test -count=1 -v ./connectors/%s/...' % (overrides_str, connector),
labels=['Test'],
auto_init=False,
resource_deps=['catalog'] + extra_deps,
allow_parallel=True,
)

# These are overrides to provide different MySQL flavors with the same test definitions.

def resolve_env(var_name):
for line in str(read_file('.env')).splitlines():
if line.startswith(var_name + '='):
return line.strip().split('=', 1)[1]
return None

mysql_gtid_vars = {
'CI_MYSQL_PORT': resolve_env('CI_MYSQL_GTID_PORT'),
'CI_MYSQL_VERSION': resolve_env('CI_MYSQL_GTID_VERSION'),
}
mysql_pos_vars = {
'CI_MYSQL_PORT': resolve_env('CI_MYSQL_POS_PORT'),
'CI_MYSQL_VERSION': resolve_env('CI_MYSQL_POS_VERSION'),
}
mariadb_vars = {
'CI_MYSQL_PORT': resolve_env('CI_MARIADB_PORT'),
'CI_MYSQL_VERSION': resolve_env('CI_MARIADB_VERSION'),
}

# Generic e2e tests

# Postgres to ClickHouse generic tests
e2e_test('postgres', 'TestGenericCH_PG', ['provision-postgres'])

# MySQL GTID to ClickHouse generic tests
e2e_test('mysql-gtid', 'TestGenericCH_MySQL', ['provision-mysql-gtid'], vars_overrides={'CI_MYSQL_PORT': '$CI_MYSQL_GTID_PORT'})
e2e_test('mysql-gtid', 'TestGenericCH_MySQL', ['provision-mysql-gtid'], vars_overrides=mysql_gtid_vars)

# MySQL Pos to ClickHouse generic tests
e2e_test('mysql-pos', 'TestGenericCH_MySQL', ['provision-mysql-pos'], vars_overrides={'CI_MYSQL_PORT': '$CI_MYSQL_POS_PORT'})
e2e_test('mysql-pos', 'TestGenericCH_MySQL', ['provision-mysql-pos'], vars_overrides=mysql_pos_vars)

# MariaDB to ClickHouse generic tests
e2e_test('mariadb', 'TestGenericCH_MySQL', ['provision-mariadb'], vars_overrides={'CI_MYSQL_PORT': '$CI_MARIADB_PORT'})
e2e_test('mariadb', 'TestGenericCH_MySQL', ['provision-mariadb'], vars_overrides=mariadb_vars)

# MongoDB to ClickHouse test suite
e2e_test('mongodb', 'TestMongoClickhouseSuite', ['provision-mongodb'])

# Switchboard tests

e2e_test('switchboard-postgres', 'TestSwitchboardPostgres', ['provision-postgres'])

e2e_test('switchboard-mysql-gtid', 'TestSwitchboardMySQL', ['provision-mysql-gtid'], vars_overrides=mysql_gtid_vars)
e2e_test('switchboard-mysql-pos', 'TestSwitchboardMySQL', ['provision-mysql-pos'], vars_overrides=mysql_pos_vars)
e2e_test('switchboard-mariadb', 'TestSwitchboardMySQL', ['provision-mariadb'], vars_overrides=mariadb_vars)

e2e_test('switchboard-mongodb', 'TestSwitchboardMongo', ['provision-mongodb'])

# Peer flow E2E

e2e_test('peer-flow-postgres', '^TestPeerFlowE2ETestSuitePG_CH$', ['provision-postgres'])

e2e_test('peer-flow-mysql-gtid', '^TestPeerFlowE2ETestSuiteMySQL_CH$', ['provision-mysql-gtid'], vars_overrides=mysql_gtid_vars)
e2e_test('peer-flow-mysql-pos', '^TestPeerFlowE2ETestSuiteMySQL_CH$', ['provision-mysql-pos'], vars_overrides=mysql_pos_vars)
e2e_test('peer-flow-mariadb', '^TestPeerFlowE2ETestSuiteMySQL_CH$', ['provision-mariadb'], vars_overrides=mariadb_vars)

# API e2e tests

e2e_test('api-postgres', 'TestApiPg', ['provision-postgres'])

e2e_test('api-mysql-gtid', 'TestApiMy', ['provision-mysql-gtid', 'provision-postgres'], vars_overrides=mysql_gtid_vars)
e2e_test('api-mysql-pos', 'TestApiMy', ['provision-mysql-pos', 'provision-postgres'], vars_overrides=mysql_pos_vars)
e2e_test('api-mariadb', 'TestApiMy', ['provision-mariadb', 'provision-postgres'], vars_overrides=mariadb_vars)

e2e_test('api-mongodb', 'TestApiMongo', ['provision-mongodb'])

# Connectors tests

connector_test('postgres', ['provision-postgres'])
connector_test('mongo', ['provision-mongodb'])
connector_test('mysql', ['provision-mysql-gtid'])
connector_test('clickhouse', ['provision-clickhouse'])
13 changes: 13 additions & 0 deletions flow/connectors/utils/autoenv.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package utils

import (
"testing"

"github.com/PeerDB-io/peerdb/flow/internal/testutil"
)

func init() {
if testing.Testing() {
testutil.LoadEnv()
}
}
4 changes: 2 additions & 2 deletions flow/e2e/test_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (
"github.com/google/uuid"
"github.com/jackc/pgerrcode"
"github.com/jackc/pgx/v5"
"github.com/joho/godotenv"
"github.com/stretchr/testify/require"
"go.temporal.io/api/enums/v1"
"go.temporal.io/sdk/client"
Expand All @@ -30,6 +29,7 @@ import (
"github.com/PeerDB-io/peerdb/flow/generated/proto_conversions"
"github.com/PeerDB-io/peerdb/flow/generated/protos"
"github.com/PeerDB-io/peerdb/flow/internal"
"github.com/PeerDB-io/peerdb/flow/internal/testutil"
"github.com/PeerDB-io/peerdb/flow/model"
"github.com/PeerDB-io/peerdb/flow/shared"
"github.com/PeerDB-io/peerdb/flow/shared/types"
Expand All @@ -40,7 +40,7 @@ import (
func init() {
// it's okay if the .env file is not present
// we will use the default values
_ = godotenv.Load()
testutil.LoadEnv()
}

type Suite interface {
Expand Down
Loading
Loading