From 7cbd3fad4b45d1c76825e06d7068094ad8be085e Mon Sep 17 00:00:00 2001 From: mehmet Date: Fri, 3 Jul 2026 17:18:05 +0200 Subject: [PATCH 1/4] =?UTF-8?q?=F0=9F=92=9A(ci)=20fix=20check-changelog=20?= =?UTF-8?q?and=20pymongo-brittle=20mongo=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Replace removed `git whatchanged` (refused by git >= 2.47) with `git log --name-only` in the check-changelog CI job. - Assert only on the stable "Failed to delete document chunk: " prefix in the mongo delete-failure tests, instead of the exact pymongo/bson error string which varies across pymongo versions. --- .circleci/config.yml | 2 +- CHANGELOG.md | 3 +++ tests/backends/data/test_async_mongo.py | 22 +++++++++++----------- tests/backends/data/test_mongo.py | 25 +++++++++++++++++-------- 4 files changed, 32 insertions(+), 20 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 146ba4e8c..27b44f4ee 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -77,7 +77,7 @@ jobs: - run: name: Check that the CHANGELOG has been modified in the current branch command: | - git whatchanged --name-only --pretty="" origin..HEAD | grep CHANGELOG + git log --name-only --pretty=format: origin..HEAD | grep CHANGELOG # Check that the CHANGELOG max line length does not exceed 80 characters lint-changelog: diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f3b6ce9f..9ac703755 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,9 @@ and this project adheres to ### Fixed - Fix type of `statement.result.score.scaled` from `int` to `Decimal` +- Fix `check-changelog` CI job by replacing the removed `git whatchanged` + command with `git log --name-only` +- Make MongoDB delete-failure tests tolerant to pymongo error message changes ## [5.0.1] - 2024-07-11 diff --git a/tests/backends/data/test_async_mongo.py b/tests/backends/data/test_async_mongo.py index bad3734ae..af0608264 100644 --- a/tests/backends/data/test_async_mongo.py +++ b/tests/backends/data/test_async_mongo.py @@ -785,12 +785,11 @@ async def test_backends_data_async_mongo_write_with_delete_operation_failure( """ backend = async_mongo_backend() - msg = ( - "Failed to delete document chunk: Invalid document " - "{'q': {'_source.id': {'$in': []}}, 'limit': 0} | " - "cannot encode object: , of type: " - ) - with pytest.raises(BackendException, match=msg): + # The tail of the error message is produced by pymongo/bson and its exact + # wording changes across pymongo versions; only assert on the stable prefix + # controlled by Ralph. + msg_prefix = "Failed to delete document chunk: " + with pytest.raises(BackendException, match=re.escape(msg_prefix)): await backend.write([{"id": object}], operation_type=BaseOperationType.DELETE) # Given `ignore_errors` argument set to `True`, the `write` method should not raise @@ -805,11 +804,12 @@ async def test_backends_data_async_mongo_write_with_delete_operation_failure( == 0 ) - assert ( - "ralph.backends.data.async_mongo", - logging.WARNING, - msg, - ) in caplog.record_tuples + assert any( + name == "ralph.backends.data.async_mongo" + and level == logging.WARNING + and message.startswith(msg_prefix) + for name, level, message in caplog.record_tuples + ) @pytest.mark.anyio diff --git a/tests/backends/data/test_mongo.py b/tests/backends/data/test_mongo.py index 7caf52de3..60d47d41d 100644 --- a/tests/backends/data/test_mongo.py +++ b/tests/backends/data/test_mongo.py @@ -620,16 +620,20 @@ def test_backends_data_mongo_write_with_delete_operation_failure( """ backend = mongo_backend() - msg = ( - "Failed to delete document chunk: Invalid document {'q': {'_source.id': {'$in':" - " []}}, 'limit': 0} | cannot encode object: , " - "of type: " - ) + # The tail of the error message is produced by pymongo/bson and its exact + # wording changes across pymongo versions; only assert on the stable prefix + # controlled by Ralph. + msg_prefix = "Failed to delete document chunk: " with caplog.at_level(logging.ERROR): - with pytest.raises(BackendException, match=msg): + with pytest.raises(BackendException, match=re.escape(msg_prefix)): backend.write([{"id": object}], operation_type=BaseOperationType.DELETE) - assert ("ralph.backends.data.mongo", logging.ERROR, msg) in caplog.record_tuples + assert any( + name == "ralph.backends.data.mongo" + and level == logging.ERROR + and message.startswith(msg_prefix) + for name, level, message in caplog.record_tuples + ) # Given `ignore_errors` argument set to `True`, the `write` method should not raise # an exception. @@ -643,7 +647,12 @@ def test_backends_data_mongo_write_with_delete_operation_failure( == 0 ) - assert ("ralph.backends.data.mongo", logging.WARNING, msg) in caplog.record_tuples + assert any( + name == "ralph.backends.data.mongo" + and level == logging.WARNING + and message.startswith(msg_prefix) + for name, level, message in caplog.record_tuples + ) backend.close() From 4e4d15c9f1a79db0c84410f2da95d8b0b0ba3dec Mon Sep 17 00:00:00 2001 From: mehmet Date: Fri, 3 Jul 2026 18:32:03 +0200 Subject: [PATCH 2/4] =?UTF-8?q?=F0=9F=93=8C(ci)=20pin=20Arnold=20to=206.23?= =?UTF-8?q?.0=20to=20fix=20the=20tray=20job?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The tray job runs Arnold with an unpinned `master` image tag. Arnold's `latest`/`master` moved to 6.24.0 (ansible-core 2.14.18), whose vault handling breaks the "Decrypt vaulted credentials" step, turning tray red without any code change (green->red on unrelated PRs). Pin the Arnold image (Makefile + .k3d-cluster.env.sh) and the downloaded `bin/arnold` / `bin/init-cluster` wrappers to 6.23.0 (ansible-core 2.14.17), the last release before the regression. --- .k3d-cluster.env.sh | 2 +- CHANGELOG.md | 2 ++ Makefile | 6 +++--- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.k3d-cluster.env.sh b/.k3d-cluster.env.sh index 1b968b8a2..0d02cf292 100644 --- a/.k3d-cluster.env.sh +++ b/.k3d-cluster.env.sh @@ -4,7 +4,7 @@ echo -n "Loading k3d cluster environment... " export ARNOLD_DEFAULT_VAULT_PASSWORD=arnold export ANSIBLE_VAULT_PASSWORD="${ARNOLD_DEFAULT_VAULT_PASSWORD}" -export ARNOLD_IMAGE_TAG=master +export ARNOLD_IMAGE_TAG=6.23.0 export K3D_BIND_HOST_PORT_HTTP=80 export K3D_BIND_HOST_PORT_HTTPS=443 export K3D_CLUSTER_NAME=ralph diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ac703755..6fc70b0f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,8 @@ and this project adheres to - Fix `check-changelog` CI job by replacing the removed `git whatchanged` command with `git log --name-only` - Make MongoDB delete-failure tests tolerant to pymongo error message changes +- Pin Arnold to `6.23.0` (was `master`) to fix the CircleCI `tray` job broken + by the ansible-core `2.14.18` vault handling change ## [5.0.1] - 2024-07-11 diff --git a/Makefile b/Makefile index 185f78db2..9bd09638c 100644 --- a/Makefile +++ b/Makefile @@ -26,7 +26,7 @@ ES_INDEX = statements ES_URL = $(ES_PROTOCOL)://$(ES_HOST):$(ES_PORT) # -- Arnold -ARNOLD = ARNOLD_IMAGE_TAG=master bin/arnold +ARNOLD = ARNOLD_IMAGE_TAG=6.23.0 bin/arnold ARNOLD_APP = ralph ARNOLD_APP_VARS = group_vars/customer/$(ARNOLD_CUSTOMER)/$(ARNOLD_ENVIRONMENT)/main.yml ARNOLD_CUSTOMER ?= ralph @@ -56,11 +56,11 @@ K8S_NAMESPACE = $(ARNOLD_ENVIRONMENT)-$(ARNOLD_CUSTOMER) default: help bin/arnold: - curl -Lo "bin/arnold" "https://raw.githubusercontent.com/openfun/arnold/master/bin/arnold" + curl -Lo "bin/arnold" "https://raw.githubusercontent.com/openfun/arnold/v6.23.0/bin/arnold" chmod +x bin/arnold bin/init-cluster: - curl -Lo "bin/init-cluster" "https://raw.githubusercontent.com/openfun/arnold/master/bin/init-cluster" + curl -Lo "bin/init-cluster" "https://raw.githubusercontent.com/openfun/arnold/v6.23.0/bin/init-cluster" chmod +x bin/init-cluster .env: From 90f645e54be6a86b2762c7af6c826e560267b5e3 Mon Sep 17 00:00:00 2001 From: mehmet Date: Fri, 3 Jul 2026 18:54:41 +0200 Subject: [PATCH 3/4] =?UTF-8?q?=F0=9F=92=9A(ci)=20fix=20test-helm=20elasti?= =?UTF-8?q?csearch=20deployment=20race?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The test-helm job installed the ECK operator from an unpinned chart and then waited on pods with a 5s sleep. The freshly installed operator was not ready yet, so no pods existed and `kubectl wait` failed immediately with "no matching resources found". Pin eck-operator to 2.16.1, wait for the operator to be ready before applying the Elasticsearch CR, and wait on the Elasticsearch resource status (which exists right after apply) instead of racing on pods. --- .circleci/config.yml | 16 ++++++++++------ CHANGELOG.md | 2 ++ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 27b44f4ee..ef0bd4239 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -378,16 +378,20 @@ jobs: command: | helm repo add elastic https://helm.elastic.co helm repo update - helm install elastic-operator elastic/eck-operator + # Pin the ECK operator: an unpinned chart drifts and breaks CI + helm install elastic-operator elastic/eck-operator --version 2.16.1 + + # The operator must be running before it can reconcile the + # Elasticsearch resource, otherwise no pods are ever created. + kubectl rollout status statefulset/elastic-operator --timeout=300s # Deploy a two-nodes elasticsearch cluster kubectl apply -f src/helm/manifests/data-lake.yml - # Wait for pods to be ready - # Still need to wait for pods to be created before waiting for them - # to be ready (see https://github.com/kubernetes/kubectl/issues/1516) - sleep 5 - kubectl wait --for=condition=ready pod --selector=common.k8s.elastic.co/type=elasticsearch --timeout=120s + # Wait on the Elasticsearch resource itself: it exists right after + # `apply`, so this avoids the "no matching resources found" race of + # `kubectl wait pod` against an empty selector (see kubectl#1516). + kubectl wait --for=jsonpath='{.status.phase}'=Ready elasticsearch/data-lake --timeout=600s # Store elastic user password echo 'ELASTIC_PASSWORD="$(kubectl get secret data-lake-es-elastic-user -o jsonpath="{.data.elastic}" | base64 -d)"' >> $BASH_ENV diff --git a/CHANGELOG.md b/CHANGELOG.md index 6fc70b0f4..86de709ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,8 @@ and this project adheres to - Make MongoDB delete-failure tests tolerant to pymongo error message changes - Pin Arnold to `6.23.0` (was `master`) to fix the CircleCI `tray` job broken by the ansible-core `2.14.18` vault handling change +- Pin the ECK operator and wait on the Elasticsearch resource in the + `test-helm` CI job to fix a "no matching resources found" race ## [5.0.1] - 2024-07-11 From 46e0a54327219fd4c8b57542d7856bd1d5d6757a Mon Sep 17 00:00:00 2001 From: mehmet Date: Fri, 3 Jul 2026 19:15:12 +0200 Subject: [PATCH 4/4] =?UTF-8?q?=F0=9F=92=9A(ci)=20poll=20elasticsearch=20s?= =?UTF-8?q?tatus=20in=20test-helm?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `kubectl wait --for=jsonpath` fails immediately with "status is not found" when the ECK operator has not written the Elasticsearch `.status` subresource yet (it does so asynchronously after apply). Replace it with a polling loop that waits until `.status.phase` reaches `Ready`, logging the phase on each iteration for easier debugging. --- .circleci/config.yml | 14 ++++++++++---- CHANGELOG.md | 4 ++-- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index ef0bd4239..a38599b3e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -388,10 +388,16 @@ jobs: # Deploy a two-nodes elasticsearch cluster kubectl apply -f src/helm/manifests/data-lake.yml - # Wait on the Elasticsearch resource itself: it exists right after - # `apply`, so this avoids the "no matching resources found" race of - # `kubectl wait pod` against an empty selector (see kubectl#1516). - kubectl wait --for=jsonpath='{.status.phase}'=Ready elasticsearch/data-lake --timeout=600s + # The operator writes `.status` asynchronously, so `kubectl wait + # --for=jsonpath` errors with "status is not found" when the field + # does not exist yet. Poll until the cluster reports a Ready phase. + for i in $(seq 1 60); do + phase=$(kubectl get elasticsearch data-lake -o jsonpath='{.status.phase}' 2>/dev/null || true) + echo "Elasticsearch phase: ${phase:-} ($i/60)" + if [ "$phase" = "Ready" ]; then break; fi + sleep 10 + done + [ "$phase" = "Ready" ] # Store elastic user password echo 'ELASTIC_PASSWORD="$(kubectl get secret data-lake-es-elastic-user -o jsonpath="{.data.elastic}" | base64 -d)"' >> $BASH_ENV diff --git a/CHANGELOG.md b/CHANGELOG.md index 86de709ce..2d09a386a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,8 +20,8 @@ and this project adheres to - Make MongoDB delete-failure tests tolerant to pymongo error message changes - Pin Arnold to `6.23.0` (was `master`) to fix the CircleCI `tray` job broken by the ansible-core `2.14.18` vault handling change -- Pin the ECK operator and wait on the Elasticsearch resource in the - `test-helm` CI job to fix a "no matching resources found" race +- Pin the ECK operator and poll the Elasticsearch resource status in the + `test-helm` CI job to fix flaky "no matching resources"/"status not found" ## [5.0.1] - 2024-07-11