From 19f004ccc3af018729c7f60ebf51e7d777926716 Mon Sep 17 00:00:00 2001 From: Artem Savchenko Date: Thu, 12 Mar 2026 16:29:33 +0700 Subject: [PATCH 1/8] Fix KVS migration Signed-off-by: Artem Savchenko --- .github/workflows/pr-checks.yml | 111 ++++++++++++++++++++++++++++++++ hulykvs_server/src/main.rs | 35 ++++++++-- 2 files changed, 139 insertions(+), 7 deletions(-) diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml index 1f13a6c..e2cfce1 100644 --- a/.github/workflows/pr-checks.yml +++ b/.github/workflows/pr-checks.yml @@ -29,6 +29,117 @@ jobs: - name: Tests run: cargo test --workspace --all-targets --locked + db-startup: + runs-on: ubuntu-latest + + services: + postgres: + image: postgres:15 + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: postgres + ports: + - 5432:5432 + options: >- + --health-cmd="pg_isready -U postgres" + --health-interval=5s + --health-timeout=5s + --health-retries=10 + + cockroach: + image: cockroachdb/cockroach:v24.1.0 + ports: + - 26257:26257 + command: start-single-node --insecure --listen-addr=0.0.0.0 --http-addr=0.0.0.0:8080 + options: >- + --health-cmd="cockroach node status --host=localhost:26257 --insecure || exit 1" + --health-interval=5s + --health-timeout=5s + --health-retries=20 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Rust + uses: dtolnay/rust-toolchain@stable + with: + toolchain: "1.88.0" + + - name: Rust cache + uses: Swatinem/rust-cache@v2 + + - name: Build hulykvs server (release) + run: cargo build --bin hulykvs --release --locked + working-directory: hulykvs_server + + - name: Wait for databases to be ready + run: | + set -euo pipefail + + echo "Waiting for PostgreSQL..." + for i in {1..30}; do + if PGPASSWORD=postgres psql -h localhost -U postgres -d postgres -c "SELECT 1" >/dev/null 2>&1; then + echo "PostgreSQL is up." + break + fi + sleep 2 + done + + echo "Waiting for CockroachDB..." + for i in {1..30}; do + if cockroach sql --host=localhost:26257 --insecure -e "SELECT 1" >/dev/null 2>&1; then + echo "CockroachDB is up." + break + fi + sleep 2 + done + + - name: Smoke test startup with PostgreSQL + run: | + set -euo pipefail + + export HULY_DB_CONNECTION="postgresql://postgres:postgres@localhost:5432/postgres?sslmode=disable" + export HULY_TOKEN_SECRET="secret" + + ./target/release/hulykvs & + SERVER_PID=$! + + for i in {1..30}; do + if curl -fsS http://localhost:8094/status >/dev/null 2>&1; then + echo "hulykvs started successfully with PostgreSQL." + break + fi + sleep 2 + done + + kill "$SERVER_PID" || true + wait "$SERVER_PID" || true + working-directory: hulykvs_server + + - name: Smoke test startup with CockroachDB + run: | + set -euo pipefail + + export HULY_DB_CONNECTION="postgresql://root@localhost:26257/defaultdb?sslmode=disable" + export HULY_TOKEN_SECRET="secret" + + ./target/release/hulykvs & + SERVER_PID=$! + + for i in {1..30}; do + if curl -fsS http://localhost:8094/status >/dev/null 2>&1; then + echo "hulykvs started successfully with CockroachDB." + break + fi + sleep 2 + done + + kill "$SERVER_PID" || true + wait "$SERVER_PID" || true + working-directory: hulykvs_server + docker-build-verify: runs-on: ubuntu-latest diff --git a/hulykvs_server/src/main.rs b/hulykvs_server/src/main.rs index 51ccfc3..df3990e 100644 --- a/hulykvs_server/src/main.rs +++ b/hulykvs_server/src/main.rs @@ -148,16 +148,37 @@ async fn main() -> anyhow::Result<()> { let report = match backend { DbBackend::Cockroach => { - migrations_crdb::migrations::runner() + let runner = migrations_crdb::migrations::runner() .set_migration_table_name("migrations") - .run_async(&mut connection) - .await? + .set_abort_divergent(false); + + match runner.run_async(&mut connection).await { + Ok(report) => report, + Err(err) => { + tracing::error!( + %err, + ?backend, + "failed to run CockroachDB migrations; this often means an applied migration in the 'migrations' table differs from the file in 'etc/migrations'. Consider checking the 'migrations' table and the contents of the corresponding SQL file." + ); + return Err(err.into()); + } + } } DbBackend::Postgres => { - migrations_pg::migrations::runner() - .set_migration_table_name("migrations_pg") - .run_async(&mut connection) - .await? + let runner = migrations_pg::migrations::runner() + .set_migration_table_name("migrations_pg"); + + match runner.run_async(&mut connection).await { + Ok(report) => report, + Err(err) => { + tracing::error!( + %err, + ?backend, + "failed to run PostgreSQL migrations; this often means an applied migration in the 'migrations_pg' table differs from the file in 'etc/migrations_pg'. Consider checking the 'migrations_pg' table and the contents of the corresponding SQL file." + ); + return Err(err.into()); + } + } } }; From 1cdbcbfa556075c673458b2916f6a625c8085fac Mon Sep 17 00:00:00 2001 From: Artem Savchenko Date: Thu, 12 Mar 2026 16:32:33 +0700 Subject: [PATCH 2/8] Fix ci Signed-off-by: Artem Savchenko --- .github/workflows/pr-checks.yml | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml index e2cfce1..02cecda 100644 --- a/.github/workflows/pr-checks.yml +++ b/.github/workflows/pr-checks.yml @@ -47,17 +47,6 @@ jobs: --health-timeout=5s --health-retries=10 - cockroach: - image: cockroachdb/cockroach:v24.1.0 - ports: - - 26257:26257 - command: start-single-node --insecure --listen-addr=0.0.0.0 --http-addr=0.0.0.0:8080 - options: >- - --health-cmd="cockroach node status --host=localhost:26257 --insecure || exit 1" - --health-interval=5s - --health-timeout=5s - --health-retries=20 - steps: - name: Checkout uses: actions/checkout@v4 @@ -78,6 +67,12 @@ jobs: run: | set -euo pipefail + echo "Starting CockroachDB container..." + docker run -d --name crdb \ + -p 26257:26257 -p 8080:8080 \ + cockroachdb/cockroach:v24.1.0 \ + start-single-node --insecure --listen-addr=0.0.0.0:26257 --http-addr=0.0.0.0:8080 + echo "Waiting for PostgreSQL..." for i in {1..30}; do if PGPASSWORD=postgres psql -h localhost -U postgres -d postgres -c "SELECT 1" >/dev/null 2>&1; then @@ -89,7 +84,7 @@ jobs: echo "Waiting for CockroachDB..." for i in {1..30}; do - if cockroach sql --host=localhost:26257 --insecure -e "SELECT 1" >/dev/null 2>&1; then + if docker exec crdb cockroach sql --host=localhost:26257 --insecure -e "SELECT 1" >/dev/null 2>&1; then echo "CockroachDB is up." break fi From 6d057e017f65866145d59b7a862dd18bf337ae41 Mon Sep 17 00:00:00 2001 From: Artem Savchenko Date: Thu, 12 Mar 2026 16:37:28 +0700 Subject: [PATCH 3/8] Fix build Signed-off-by: Artem Savchenko --- hulykvs_server/src/main.rs | 36 ++++++++---------------------------- 1 file changed, 8 insertions(+), 28 deletions(-) diff --git a/hulykvs_server/src/main.rs b/hulykvs_server/src/main.rs index df3990e..d0906e4 100644 --- a/hulykvs_server/src/main.rs +++ b/hulykvs_server/src/main.rs @@ -148,37 +148,17 @@ async fn main() -> anyhow::Result<()> { let report = match backend { DbBackend::Cockroach => { - let runner = migrations_crdb::migrations::runner() + migrations_crdb::migrations::runner() .set_migration_table_name("migrations") - .set_abort_divergent(false); - - match runner.run_async(&mut connection).await { - Ok(report) => report, - Err(err) => { - tracing::error!( - %err, - ?backend, - "failed to run CockroachDB migrations; this often means an applied migration in the 'migrations' table differs from the file in 'etc/migrations'. Consider checking the 'migrations' table and the contents of the corresponding SQL file." - ); - return Err(err.into()); - } - } + .set_abort_divergent(false) + .run_async(&mut connection) + .await? } DbBackend::Postgres => { - let runner = migrations_pg::migrations::runner() - .set_migration_table_name("migrations_pg"); - - match runner.run_async(&mut connection).await { - Ok(report) => report, - Err(err) => { - tracing::error!( - %err, - ?backend, - "failed to run PostgreSQL migrations; this often means an applied migration in the 'migrations_pg' table differs from the file in 'etc/migrations_pg'. Consider checking the 'migrations_pg' table and the contents of the corresponding SQL file." - ); - return Err(err.into()); - } - } + migrations_pg::migrations::runner() + .set_migration_table_name("migrations_pg") + .run_async(&mut connection) + .await? } }; From 5d850f60667ce86f3d2e6f4b35d91a37682141b9 Mon Sep 17 00:00:00 2001 From: Artem Savchenko Date: Thu, 12 Mar 2026 16:49:56 +0700 Subject: [PATCH 4/8] Fix build Signed-off-by: Artem Savchenko --- hulykvs_server/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hulykvs_server/src/main.rs b/hulykvs_server/src/main.rs index d0906e4..71eecce 100644 --- a/hulykvs_server/src/main.rs +++ b/hulykvs_server/src/main.rs @@ -149,8 +149,8 @@ async fn main() -> anyhow::Result<()> { let report = match backend { DbBackend::Cockroach => { migrations_crdb::migrations::runner() - .set_migration_table_name("migrations") .set_abort_divergent(false) + .set_migration_table_name("migrations") .run_async(&mut connection) .await? } From ff6969468c0ec80e6c7b122797e400cb3135be57 Mon Sep 17 00:00:00 2001 From: Artem Savchenko Date: Thu, 12 Mar 2026 17:00:42 +0700 Subject: [PATCH 5/8] Fix smoke test Signed-off-by: Artem Savchenko --- .github/workflows/pr-checks.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml index 02cecda..7d6529e 100644 --- a/.github/workflows/pr-checks.yml +++ b/.github/workflows/pr-checks.yml @@ -98,7 +98,7 @@ jobs: export HULY_DB_CONNECTION="postgresql://postgres:postgres@localhost:5432/postgres?sslmode=disable" export HULY_TOKEN_SECRET="secret" - ./target/release/hulykvs & + ../target/release/hulykvs & SERVER_PID=$! for i in {1..30}; do @@ -120,7 +120,7 @@ jobs: export HULY_DB_CONNECTION="postgresql://root@localhost:26257/defaultdb?sslmode=disable" export HULY_TOKEN_SECRET="secret" - ./target/release/hulykvs & + ../target/release/hulykvs & SERVER_PID=$! for i in {1..30}; do From 03df876aefe09b103ee17b116726362abcaeb0a4 Mon Sep 17 00:00:00 2001 From: Artem Savchenko Date: Thu, 12 Mar 2026 17:08:36 +0700 Subject: [PATCH 6/8] Fix cockroach test Signed-off-by: Artem Savchenko --- .github/workflows/pr-checks.yml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml index 7d6529e..0c9373f 100644 --- a/.github/workflows/pr-checks.yml +++ b/.github/workflows/pr-checks.yml @@ -74,22 +74,35 @@ jobs: start-single-node --insecure --listen-addr=0.0.0.0:26257 --http-addr=0.0.0.0:8080 echo "Waiting for PostgreSQL..." + pg_ok=0 for i in {1..30}; do if PGPASSWORD=postgres psql -h localhost -U postgres -d postgres -c "SELECT 1" >/dev/null 2>&1; then echo "PostgreSQL is up." + pg_ok=1 break fi sleep 2 done + if [ "$pg_ok" -ne 1 ]; then + echo "PostgreSQL did not become ready in time." + exit 1 + fi echo "Waiting for CockroachDB..." + crdb_ok=0 for i in {1..30}; do if docker exec crdb cockroach sql --host=localhost:26257 --insecure -e "SELECT 1" >/dev/null 2>&1; then echo "CockroachDB is up." + crdb_ok=1 break fi sleep 2 done + if [ "$crdb_ok" -ne 1 ]; then + echo "CockroachDB did not become ready in time. Container logs:" + docker logs crdb || true + exit 1 + fi - name: Smoke test startup with PostgreSQL run: | @@ -101,13 +114,19 @@ jobs: ../target/release/hulykvs & SERVER_PID=$! + ok=0 for i in {1..30}; do if curl -fsS http://localhost:8094/status >/dev/null 2>&1; then echo "hulykvs started successfully with PostgreSQL." + ok=1 break fi sleep 2 done + if [ "$ok" -ne 1 ]; then + echo "hulykvs did not start successfully with PostgreSQL (no /status response)." + exit 1 + fi kill "$SERVER_PID" || true wait "$SERVER_PID" || true @@ -123,13 +142,19 @@ jobs: ../target/release/hulykvs & SERVER_PID=$! + ok=0 for i in {1..30}; do if curl -fsS http://localhost:8094/status >/dev/null 2>&1; then echo "hulykvs started successfully with CockroachDB." + ok=1 break fi sleep 2 done + if [ "$ok" -ne 1 ]; then + echo "hulykvs did not start successfully with CockroachDB (no /status response)." + exit 1 + fi kill "$SERVER_PID" || true wait "$SERVER_PID" || true From 08c4e9b79be94cd60656a910edb55c1bbf06536a Mon Sep 17 00:00:00 2001 From: Artem Savchenko Date: Thu, 12 Mar 2026 17:11:49 +0700 Subject: [PATCH 7/8] Fix cockroach start Signed-off-by: Artem Savchenko --- .github/workflows/pr-checks.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml index 0c9373f..5ddab1a 100644 --- a/.github/workflows/pr-checks.yml +++ b/.github/workflows/pr-checks.yml @@ -71,7 +71,7 @@ jobs: docker run -d --name crdb \ -p 26257:26257 -p 8080:8080 \ cockroachdb/cockroach:v24.1.0 \ - start-single-node --insecure --listen-addr=0.0.0.0:26257 --http-addr=0.0.0.0:8080 + start-single-node --insecure --listen-addr=localhost:26257 --http-addr=localhost:8080 echo "Waiting for PostgreSQL..." pg_ok=0 From f53b22319c5fc2dc3103effd74dd42d980f6a1fe Mon Sep 17 00:00:00 2001 From: Artem Savchenko Date: Thu, 12 Mar 2026 20:30:34 +0700 Subject: [PATCH 8/8] Update cockroach config Signed-off-by: Artem Savchenko --- .github/workflows/pr-checks.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml index 5ddab1a..135af78 100644 --- a/.github/workflows/pr-checks.yml +++ b/.github/workflows/pr-checks.yml @@ -67,11 +67,11 @@ jobs: run: | set -euo pipefail - echo "Starting CockroachDB container..." + echo "Starting CockroachDB container (v24.x, insecure single node)..." docker run -d --name crdb \ - -p 26257:26257 -p 8080:8080 \ - cockroachdb/cockroach:v24.1.0 \ - start-single-node --insecure --listen-addr=localhost:26257 --http-addr=localhost:8080 + -p 26257:26257 -p 8089:8080 \ + cockroachdb/cockroach:latest-v24.3 \ + start-single-node --insecure echo "Waiting for PostgreSQL..." pg_ok=0 @@ -136,7 +136,7 @@ jobs: run: | set -euo pipefail - export HULY_DB_CONNECTION="postgresql://root@localhost:26257/defaultdb?sslmode=disable" + export HULY_DB_CONNECTION="postgresql://root@127.0.0.1:26257/defaultdb?sslmode=disable" export HULY_TOKEN_SECRET="secret" ../target/release/hulykvs &