Skip to content

Commit a74fea0

Browse files
committed
Setup CI for adapter with service dependencies
Run the Kafka adapter integration tests in CI against a real broker. Adds a test_adapters job that stands up ci/kafka/docker-compose.yml, sets CSP_TEST_<ADAPTER>, and runs the matching tests, plus dockerup/dockerps/dockerdown targets for doing the same locally. The compose stack is trimmed to zookeeper and a single broker, with healthchecks so `docker compose up --wait` blocks until the broker accepts connections rather than relying on a fixed sleep. Only 9092 is published, bound to loopback. Broker-side topic auto-creation is disabled so test_invalid_topic can exercise the failure path, and tests create their topics explicitly through the Kafka AdminClient. Test changes target the startup race where a subscriber misses the first few records while its consumer group is being assigned. Rather than loosening the assertions, the affected tests align on the first record the subscriber saw and then require an exact contiguous run, so loss, duplication and reordering are still caught. Also drops curl from the Windows chocolatey install: the package fails whenever a new version is approved on the community feed before it is downloadable, and curl.exe ships with Windows. Signed-off-by: Tim Paine <3105306+timkpaine@users.noreply.github.com>
1 parent 1b037b2 commit a74fea0

13 files changed

Lines changed: 233 additions & 286 deletions

File tree

.github/workflows/build.yml

Lines changed: 70 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -601,7 +601,6 @@ jobs:
601601
env:
602602
CSP_TEST_SKIP_EXAMPLES: "1"
603603

604-
605604
####################################################
606605
#..................................................#
607606
#..|########|..|########|..../####\....|########|..#
@@ -713,7 +712,75 @@ jobs:
713712
###########################################################################################################
714713
# Test Service Adapters #
715714
###########################################################################################################
716-
# Coming soon!
715+
test_adapters:
716+
needs:
717+
- initialize
718+
- build
719+
720+
permissions:
721+
contents: read
722+
723+
timeout-minutes: 30
724+
725+
strategy:
726+
matrix:
727+
os:
728+
- ubuntu-24.04
729+
python-version:
730+
- 3.11
731+
adapter:
732+
- kafka
733+
734+
runs-on: ${{ matrix.os }}
735+
736+
steps:
737+
- name: Checkout
738+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
739+
with:
740+
submodules: recursive
741+
persist-credentials: false
742+
743+
- name: Set up Python ${{ matrix.python-version }}
744+
uses: ./.github/actions/setup-python
745+
with:
746+
version: '${{ matrix.python-version }}'
747+
cibuildwheel: false
748+
749+
- name: Install python dependencies
750+
run: make requirements
751+
752+
- name: Install test dependencies
753+
shell: bash
754+
run: sudo apt-get update && sudo apt-get install -y graphviz
755+
756+
# Download artifact
757+
- name: Download wheel
758+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
759+
with:
760+
name: csp-dist-${{ runner.os }}-${{ runner.arch }}-${{ matrix.python-version }}
761+
762+
- name: Install wheel
763+
run: |
764+
python -m pip install -U *manylinux*.whl
765+
python -m pip install -U --no-deps *manylinux*.whl --target .
766+
767+
# Services declare healthchecks, so --wait blocks until the broker actually accepts connections
768+
- name: Spin up adapter service
769+
run: make dockerup ADAPTER=${{ matrix.adapter }} DOCKERARGS="--wait --wait-timeout 180"
770+
771+
# Run tests
772+
- name: Setup test flags
773+
shell: bash
774+
env:
775+
ADAPTER: ${{ matrix.adapter }}
776+
run: echo "CSP_TEST_${ADAPTER^^}=1" >> "$GITHUB_ENV"
777+
778+
- name: Python Test Steps
779+
run: make test-py TEST_ARGS="-k ${{ matrix.adapter }}"
780+
781+
- name: Spin down adapter service
782+
run: make dockerdown ADAPTER=${{ matrix.adapter }}
783+
if: ${{ always() }}
717784

718785
############################################################################################
719786
#..........................................................................................#
@@ -728,7 +795,6 @@ jobs:
728795
############################################################################################
729796
# Upload Release Artifacts #
730797
############################################################################################
731-
732798
# only publish artifacts on tags, but otherwise this always runs
733799
# Note this whole workflow only triggers on release tags (e.g. "v0.1.0")
734800
publish_release_artifacts:
@@ -740,6 +806,7 @@ jobs:
740806
- test
741807
- test_sdist
742808
- test_dependencies
809+
- test_adapters
743810

744811
if: startsWith(github.ref, 'refs/tags/v')
745812
runs-on: ubuntu-24.04

Makefile

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -117,21 +117,23 @@ tests: test
117117

118118
.PHONY: dockerup dockerps dockerdown initpodmanmac
119119
ADAPTER := kafka
120-
DOCKER := podman
120+
# Prefer docker, fall back to podman-compose; override with DOCKER_COMPOSE=...
121+
DOCKER_COMPOSE := $(shell command -v docker >/dev/null 2>&1 && echo "docker compose" || echo "podman-compose")
122+
DOCKERARGS :=
121123

122124
initpodmanmac:
123125
podman machine stop
124126
podman machine set --cpus 4 --memory 8096
125127
podman machine start
126128

127129
dockerup: ## spin up docker compose services for adapter testing
128-
$(DOCKER) compose -f ci/$(ADAPTER)/docker-compose.yml up -d
130+
$(DOCKER_COMPOSE) -f ci/$(ADAPTER)/docker-compose.yml up -d $(DOCKERARGS)
129131

130-
dockerps: ## spin up docker compose services for adapter testing
131-
$(DOCKER) compose -f ci/$(ADAPTER)/docker-compose.yml ps
132+
dockerps: ## get status of current docker compose services
133+
$(DOCKER_COMPOSE) -f ci/$(ADAPTER)/docker-compose.yml ps
132134

133-
dockerdown: ## spin up docker compose services for adapter testing
134-
$(DOCKER) compose -f ci/$(ADAPTER)/docker-compose.yml down
135+
dockerdown: ## spin down docker compose services for adapter testing
136+
$(DOCKER_COMPOSE) -f ci/$(ADAPTER)/docker-compose.yml down
135137

136138
###########
137139
# VERSION #
@@ -222,9 +224,11 @@ dependencies-fedora: ## install dependencies for linux - note that zip is neede
222224
dependencies-vcpkg: ## install dependencies via vcpkg
223225
cd vcpkg && ./bootstrap-vcpkg.sh && ./vcpkg install
224226

227+
# curl.exe ships with Windows; installing it from choco breaks whenever a new version is
228+
# approved on the feed before the package is actually downloadable
225229
dependencies-win: ## install dependencies via windows
226230
choco install cmake --version=3.31.6 --allow-downgrade
227-
choco install curl winflexbison ninja unzip --no-progress -y
231+
choco install winflexbison ninja unzip --no-progress -y
228232

229233
############################################################################################
230234
# Thanks to Francoise at marmelab.com for this

ci/kafka/docker-compose.yml

Lines changed: 35 additions & 169 deletions
Original file line numberDiff line numberDiff line change
@@ -1,181 +1,47 @@
1-
# https://docs.confluent.io/platform/current/platform-quickstart.html
2-
# https://raw.githubusercontent.com/confluentinc/cp-all-in-one/7.5.3-post/cp-all-in-one-kraft/docker-compose.yml
1+
# https://github.com/conduktor/kafka-stack-docker-compose
32
---
4-
version: '2'
53
services:
6-
zookeeper:
4+
zoo1:
75
image: confluentinc/cp-zookeeper:7.5.3
8-
hostname: zookeeper
9-
container_name: zookeeper
6+
hostname: zoo1
7+
container_name: zoo1
108
ports:
11-
- "2181:2181"
9+
- "127.0.0.1:2181:2181"
1210
environment:
1311
ZOOKEEPER_CLIENT_PORT: 2181
14-
ZOOKEEPER_TICK_TIME: 2000
15-
16-
broker:
17-
image: confluentinc/cp-server:7.5.3
18-
hostname: broker
19-
container_name: broker
20-
depends_on:
21-
- zookeeper
12+
ZOOKEEPER_SERVER_ID: 1
13+
ZOOKEEPER_SERVERS: zoo1:2888:3888
14+
healthcheck:
15+
test: ["CMD-SHELL", "echo ruok | nc -w 2 localhost 2181 | grep imok"]
16+
interval: 5s
17+
timeout: 5s
18+
retries: 24
19+
20+
kafka1:
21+
image: confluentinc/cp-kafka:7.5.3
22+
hostname: kafka1
23+
container_name: kafka1
2224
ports:
23-
- "9092:9092"
24-
- "9101:9101"
25+
- "127.0.0.1:9092:9092"
2526
environment:
27+
KAFKA_ADVERTISED_LISTENERS: INTERNAL://kafka1:19092,EXTERNAL://${DOCKER_HOST_IP:-127.0.0.1}:9092
28+
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT
29+
KAFKA_INTER_BROKER_LISTENER_NAME: INTERNAL
30+
KAFKA_ZOOKEEPER_CONNECT: "zoo1:2181"
2631
KAFKA_BROKER_ID: 1
27-
KAFKA_ZOOKEEPER_CONNECT: 'zookeeper:2181'
28-
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
29-
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://broker:29092,PLAINTEXT_HOST://localhost:9092
30-
KAFKA_METRIC_REPORTERS: io.confluent.metrics.reporter.ConfluentMetricsReporter
32+
KAFKA_LOG4J_LOGGERS: "kafka.controller=INFO,kafka.producer.async.DefaultEventHandler=INFO,state.change.logger=INFO"
3133
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
32-
KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 0
33-
KAFKA_CONFLUENT_LICENSE_TOPIC_REPLICATION_FACTOR: 1
34-
KAFKA_CONFLUENT_BALANCER_TOPIC_REPLICATION_FACTOR: 1
35-
KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
3634
KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
37-
KAFKA_JMX_PORT: 9101
38-
KAFKA_JMX_HOSTNAME: localhost
39-
KAFKA_CONFLUENT_SCHEMA_REGISTRY_URL: http://schema-registry:8081
40-
CONFLUENT_METRICS_REPORTER_BOOTSTRAP_SERVERS: broker:29092
41-
CONFLUENT_METRICS_REPORTER_TOPIC_REPLICAS: 1
42-
CONFLUENT_METRICS_ENABLE: 'true'
43-
CONFLUENT_SUPPORT_CUSTOMER_ID: 'anonymous'
44-
KAFKA_AUTO_CREATE_TOPICS_ENABLE: 'true'
45-
TOPIC_AUTO_CREATE: 'true'
46-
47-
schema-registry:
48-
image: confluentinc/cp-schema-registry:7.5.3
49-
hostname: schema-registry
50-
container_name: schema-registry
51-
depends_on:
52-
- broker
53-
ports:
54-
- "8081:8081"
55-
environment:
56-
SCHEMA_REGISTRY_HOST_NAME: schema-registry
57-
SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS: 'broker:29092'
58-
SCHEMA_REGISTRY_LISTENERS: http://0.0.0.0:8081
59-
60-
connect:
61-
image: cnfldemos/cp-server-connect-datagen:0.6.2-7.5.0
62-
hostname: connect
63-
container_name: connect
64-
depends_on:
65-
- broker
66-
- schema-registry
67-
ports:
68-
- "8083:8083"
69-
environment:
70-
CONNECT_BOOTSTRAP_SERVERS: 'broker:29092'
71-
CONNECT_REST_ADVERTISED_HOST_NAME: connect
72-
CONNECT_GROUP_ID: compose-connect-group
73-
CONNECT_CONFIG_STORAGE_TOPIC: docker-connect-configs
74-
CONNECT_CONFIG_STORAGE_REPLICATION_FACTOR: 1
75-
CONNECT_OFFSET_FLUSH_INTERVAL_MS: 10000
76-
CONNECT_OFFSET_STORAGE_TOPIC: docker-connect-offsets
77-
CONNECT_OFFSET_STORAGE_REPLICATION_FACTOR: 1
78-
CONNECT_STATUS_STORAGE_TOPIC: docker-connect-status
79-
CONNECT_STATUS_STORAGE_REPLICATION_FACTOR: 1
80-
CONNECT_KEY_CONVERTER: org.apache.kafka.connect.storage.StringConverter
81-
CONNECT_VALUE_CONVERTER: io.confluent.connect.avro.AvroConverter
82-
CONNECT_VALUE_CONVERTER_SCHEMA_REGISTRY_URL: http://schema-registry:8081
83-
# CLASSPATH required due to CC-2422
84-
CLASSPATH: /usr/share/java/monitoring-interceptors/monitoring-interceptors-7.5.3.jar
85-
CONNECT_PRODUCER_INTERCEPTOR_CLASSES: "io.confluent.monitoring.clients.interceptor.MonitoringProducerInterceptor"
86-
CONNECT_CONSUMER_INTERCEPTOR_CLASSES: "io.confluent.monitoring.clients.interceptor.MonitoringConsumerInterceptor"
87-
CONNECT_PLUGIN_PATH: "/usr/share/java,/usr/share/confluent-hub-components"
88-
CONNECT_LOG4J_LOGGERS: org.apache.zookeeper=ERROR,org.I0Itec.zkclient=ERROR,org.reflections=ERROR
89-
90-
control-center:
91-
image: confluentinc/cp-enterprise-control-center:7.5.3
92-
hostname: control-center
93-
container_name: control-center
94-
depends_on:
95-
- broker
96-
- schema-registry
97-
- connect
98-
- ksqldb-server
99-
ports:
100-
- "9021:9021"
101-
environment:
102-
CONTROL_CENTER_BOOTSTRAP_SERVERS: 'broker:29092'
103-
CONTROL_CENTER_CONNECT_CONNECT-DEFAULT_CLUSTER: 'connect:8083'
104-
CONTROL_CENTER_KSQL_KSQLDB1_URL: "http://ksqldb-server:8088"
105-
CONTROL_CENTER_KSQL_KSQLDB1_ADVERTISED_URL: "http://localhost:8088"
106-
CONTROL_CENTER_SCHEMA_REGISTRY_URL: "http://schema-registry:8081"
107-
CONTROL_CENTER_REPLICATION_FACTOR: 1
108-
CONTROL_CENTER_INTERNAL_TOPICS_PARTITIONS: 1
109-
CONTROL_CENTER_MONITORING_INTERCEPTOR_TOPIC_PARTITIONS: 1
110-
CONFLUENT_METRICS_TOPIC_REPLICATION: 1
111-
PORT: 9021
112-
113-
ksqldb-server:
114-
image: confluentinc/cp-ksqldb-server:7.5.3
115-
hostname: ksqldb-server
116-
container_name: ksqldb-server
117-
depends_on:
118-
- broker
119-
- connect
120-
ports:
121-
- "8088:8088"
122-
environment:
123-
KSQL_CONFIG_DIR: "/etc/ksql"
124-
KSQL_BOOTSTRAP_SERVERS: "broker:29092"
125-
KSQL_HOST_NAME: ksqldb-server
126-
KSQL_LISTENERS: "http://0.0.0.0:8088"
127-
KSQL_CACHE_MAX_BYTES_BUFFERING: 0
128-
KSQL_KSQL_SCHEMA_REGISTRY_URL: "http://schema-registry:8081"
129-
KSQL_PRODUCER_INTERCEPTOR_CLASSES: "io.confluent.monitoring.clients.interceptor.MonitoringProducerInterceptor"
130-
KSQL_CONSUMER_INTERCEPTOR_CLASSES: "io.confluent.monitoring.clients.interceptor.MonitoringConsumerInterceptor"
131-
KSQL_KSQL_CONNECT_URL: "http://connect:8083"
132-
KSQL_KSQL_LOGGING_PROCESSING_TOPIC_REPLICATION_FACTOR: 1
133-
KSQL_KSQL_LOGGING_PROCESSING_TOPIC_AUTO_CREATE: 'true'
134-
KSQL_KSQL_LOGGING_PROCESSING_STREAM_AUTO_CREATE: 'true'
135-
136-
# ksqldb-cli:
137-
# image: confluentinc/cp-ksqldb-cli:7.5.3
138-
# container_name: ksqldb-cli
139-
# depends_on:
140-
# - broker
141-
# - connect
142-
# - ksqldb-server
143-
# entrypoint: /bin/sh
144-
# tty: true
145-
146-
# ksql-datagen:
147-
# image: confluentinc/ksqldb-examples:7.5.3
148-
# hostname: ksql-datagen
149-
# container_name: ksql-datagen
150-
# depends_on:
151-
# - ksqldb-server
152-
# - broker
153-
# - schema-registry
154-
# - connect
155-
# command: "bash -c 'echo Waiting for Kafka to be ready... && \
156-
# cub kafka-ready -b broker:29092 1 40 && \
157-
# echo Waiting for Confluent Schema Registry to be ready... && \
158-
# cub sr-ready schema-registry 8081 40 && \
159-
# echo Waiting a few seconds for topic creation to finish... && \
160-
# sleep 11 && \
161-
# tail -f /dev/null'"
162-
# environment:
163-
# KSQL_CONFIG_DIR: "/etc/ksql"
164-
# STREAMS_BOOTSTRAP_SERVERS: broker:29092
165-
# STREAMS_SCHEMA_REGISTRY_HOST: schema-registry
166-
# STREAMS_SCHEMA_REGISTRY_PORT: 8081
167-
168-
rest-proxy:
169-
image: confluentinc/cp-kafka-rest:7.5.3
35+
KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
36+
# Consumer groups are created per-run, so skip the 3s default rebalance debounce
37+
KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 0
38+
# Tests create their topics explicitly; test_invalid_topic depends on this being off
39+
KAFKA_AUTO_CREATE_TOPICS_ENABLE: "false"
40+
healthcheck:
41+
test: ["CMD-SHELL", "kafka-broker-api-versions --bootstrap-server localhost:9092"]
42+
interval: 5s
43+
timeout: 10s
44+
retries: 24
17045
depends_on:
171-
- broker
172-
- schema-registry
173-
ports:
174-
- 8082:8082
175-
hostname: rest-proxy
176-
container_name: rest-proxy
177-
environment:
178-
KAFKA_REST_HOST_NAME: rest-proxy
179-
KAFKA_REST_BOOTSTRAP_SERVERS: 'broker:29092'
180-
KAFKA_REST_LISTENERS: "http://0.0.0.0:8082"
181-
KAFKA_REST_SCHEMA_REGISTRY_URL: 'http://schema-registry:8081'
46+
zoo1:
47+
condition: service_healthy

conda/dev-environment-unix.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ dependencies:
1717
- flex
1818
- graphviz
1919
- gtest
20-
- httpx>=0.20,<1
2120
- libarrow<24
2221
- libboost>=1.80.0
2322
- libboost-headers>=1.80.0
@@ -41,6 +40,7 @@ dependencies:
4140
- pytest-sugar
4241
- python>=3.10,<3.15
4342
- python-build
43+
- python-confluent-kafka
4444
- python-graphviz
4545
- python-rapidjson
4646
- pytz

conda/dev-environment-win.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ dependencies:
1717
# - flex # not available on windows
1818
- graphviz
1919
- gtest
20-
- httpx>=0.20,<1
2120
- libarrow<24
2221
- libboost>=1.80.0
2322
- libboost-headers>=1.80.0
@@ -41,6 +40,7 @@ dependencies:
4140
- pytest-sugar
4241
- python>=3.10,<3.14
4342
- python-build
43+
- python-confluent-kafka
4444
- python-graphviz
4545
- python-rapidjson
4646
- pytz

0 commit comments

Comments
 (0)