Skip to content

Commit 5287fc8

Browse files
CarliJoyalexanderankin
authored andcommitted
fix(ci): fix community test selection
Make it based on python. Simplify the module names and add a test that enforces src, tests, pyproject.toml extra and docs are in sync.
1 parent ab6cca8 commit 5287fc8

14 files changed

Lines changed: 180 additions & 109 deletions

File tree

.github/workflows/ci-community.yml

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -34,26 +34,11 @@ jobs:
3434
list-files: 'json'
3535
filters: |
3636
modules:
37-
- 'src/testcontainers/community/**'
38-
- 'tests/community/**'
37+
- '**'
3938
- name: Compute modules from files
4039
id: compute-changes
4140
run: |
42-
modules=$(echo '${{ toJson(steps.changed-files.outputs.modules_files) }}' | jq -c '
43-
[.[] |
44-
if startswith("src/testcontainers/community/") then split("/")[3]
45-
elif startswith("tests/community/") then split("/")[2]
46-
else empty
47-
end |
48-
select(. and (startswith("__") | not)) |
49-
if . == "oracle" then "oracle-free"
50-
elif . == "influxdb1" or . == "influxdb2" then "influxdb"
51-
else .
52-
end
53-
] | unique
54-
')
55-
echo "computed_modules=$modules"
56-
echo "computed_modules=$modules" >> $GITHUB_OUTPUT
41+
python3 scripts/compute_modules.py '${{ steps.changed-files.outputs.modules_files }}'
5742
outputs:
5843
changed_modules: ${{ steps.compute-changes.outputs.computed_modules }}
5944

File renamed without changes.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ test = [
131131
"paramiko>=4",
132132
"twine>=6.2.0",
133133
"anyio>=4",
134-
"tomli", # required for pyproject.toml tests, TODO: remove once we drop py3.10 support
134+
"tomli>=2.0; python_version < '3.11'", # required for pyproject.toml tests, TODO: remove once we drop py3.10 support
135135
"pytest-xdist>=3.8.0",
136136
]
137137
lint = [

scripts/compute_modules.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Extract the community module names out of lists of changed files.
4+
"""
5+
6+
import json
7+
import os
8+
import sys
9+
10+
11+
def compute_modules(files: list[str]) -> list[str]:
12+
modules = set()
13+
for f in files:
14+
if f.startswith("src/testcontainers/community/"):
15+
part = f.split("/")[3]
16+
elif f.startswith("tests/community/"):
17+
part = f.split("/")[2]
18+
else:
19+
continue
20+
if not part or part.startswith("__") or part.endswith(".md"):
21+
continue
22+
modules.add(part)
23+
return sorted(modules)
24+
25+
26+
if __name__ == "__main__":
27+
files = json.loads(sys.argv[1])
28+
modules = compute_modules(files)
29+
result = json.dumps(modules)
30+
print(f"computed_modules={result}") # noqa: T201
31+
with open(os.environ["GITHUB_OUTPUT"], "a") as fh:
32+
fh.write(f"computed_modules={result}\n")

src/testcontainers/community/influxdb/__init__.py

Lines changed: 8 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -10,91 +10,22 @@
1010
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
1111
# License for the specific language governing permissions and limitations
1212
# under the License.
13-
1413
"""
15-
testcontainers/influxdb provides means to spawn an InfluxDB instance within a Docker container.
14+
testcontainers.community.influxdb provides means to spawn an InfluxDB instance within a Docker container.
1615
17-
- this influxdb.py module provides the common mechanism to spawn an InfluxDB container.
16+
- The InfluxDbContainer provides the common mechanism to spawn an InfluxDB container.
1817
You are not likely to use this module directly.
19-
- import the InfluxDb1Container class from the influxdb1/__init__.py module to spawn
20-
a container for an InfluxDB 1.x instance
21-
- import the InfluxDb2Container class from the influxdb2/__init__.py module to spawn
22-
a container for an InfluxDB 2.x instance
18+
- Import the InfluxDb1Container class to spawn a container for an InfluxDB 1.x instance
19+
- Import the InfluxDb2Container class to spawn a container for an InfluxDB 2.x instance
2320
2421
The 2 containers are separated in different modules for 2 reasons:
2522
- because the Docker images are not designed to be used in the same way
2623
- because the InfluxDB clients are different for 1.x and 2.x versions,
2724
so you won't have to install dependencies that you do not need
2825
"""
2926

30-
from typing import Optional
31-
32-
from requests import get
33-
from requests.exceptions import ConnectionError, ReadTimeout
34-
35-
from testcontainers.core.container import DockerContainer
36-
from testcontainers.core.waiting_utils import wait_container_is_ready
37-
38-
39-
class InfluxDbContainer(DockerContainer):
40-
"""
41-
Abstract class for Docker containers of InfluxDB v1 and v2.
42-
43-
Concrete implementations for InfluxDB 1.x and 2.x are separated iun different packages
44-
because their respective clients rely on different Python libraries which we don't want
45-
to import at the same time.
46-
"""
47-
48-
def __init__(
49-
self,
50-
# Docker image name
51-
image: str,
52-
# in the container, the default port for influxdb is often 8086 and not likely to change
53-
container_port: int = 8086,
54-
# specifies the port on the host machine where influxdb is exposed; a random available port otherwise
55-
host_port: Optional[int] = None,
56-
**docker_client_kw,
57-
) -> None:
58-
super().__init__(image=image, **docker_client_kw)
59-
self.container_port = container_port
60-
self.host_port = host_port
61-
self.with_bind_ports(self.container_port, self.host_port)
62-
63-
def get_url(self) -> str:
64-
"""
65-
Returns the url to interact with the InfluxDB container (health check, REST API, etc.)
66-
"""
67-
host = self.get_container_host_ip()
68-
port = self.get_exposed_port(self.container_port)
69-
70-
return f"http://{host}:{port}"
71-
72-
@wait_container_is_ready(ConnectionError, ReadTimeout)
73-
def _health_check(self) -> dict:
74-
"""
75-
Performs a health check on the running InfluxDB container.
76-
The call is retried until it works thanks to the @wait_container_is_ready decorator.
77-
See its documentation for the max number of retries or the timeout.
78-
"""
79-
80-
url = self.get_url()
81-
response = get(f"{url}/health", timeout=1)
82-
response.raise_for_status()
83-
84-
return response.json()
85-
86-
def get_influxdb_version(self) -> str:
87-
"""
88-
Returns the version of the InfluxDB service, as returned by the healthcheck.
89-
"""
90-
91-
return self._health_check().get("version")
92-
93-
def start(self) -> "InfluxDbContainer":
94-
"""
95-
Spawns a container of the InfluxDB Docker image, ready to be used.
96-
"""
97-
super().start()
98-
self._health_check()
27+
from .base import InfluxDbContainer
28+
from .version1 import InfluxDb1Container
29+
from .version2 import InfluxDb2Container
9930

100-
return self
31+
__all__ = ["InfluxDb1Container", "InfluxDb2Container", "InfluxDbContainer"]
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
#
2+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
3+
# not use this file except in compliance with the License. You may obtain
4+
# a copy of the License at
5+
#
6+
# http://www.apache.org/licenses/LICENSE-2.0
7+
#
8+
# Unless required by applicable law or agreed to in writing, software
9+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
10+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
11+
# License for the specific language governing permissions and limitations
12+
# under the License.
13+
14+
from typing import Optional
15+
16+
from requests import get
17+
from requests.exceptions import ConnectionError, ReadTimeout
18+
19+
from testcontainers.core.container import DockerContainer
20+
from testcontainers.core.waiting_utils import wait_container_is_ready
21+
22+
23+
class InfluxDbContainer(DockerContainer):
24+
"""
25+
Abstract class for Docker containers of InfluxDB v1 and v2.
26+
27+
Concrete implementations for InfluxDB 1.x and 2.x are separated iun different packages
28+
because their respective clients rely on different Python libraries which we don't want
29+
to import at the same time.
30+
"""
31+
32+
def __init__(
33+
self,
34+
# Docker image name
35+
image: str,
36+
# in the container, the default port for influxdb is often 8086 and not likely to change
37+
container_port: int = 8086,
38+
# specifies the port on the host machine where influxdb is exposed; a random available port otherwise
39+
host_port: Optional[int] = None,
40+
**docker_client_kw,
41+
) -> None:
42+
super().__init__(image=image, **docker_client_kw)
43+
self.container_port = container_port
44+
self.host_port = host_port
45+
self.with_bind_ports(self.container_port, self.host_port)
46+
47+
def get_url(self) -> str:
48+
"""
49+
Returns the url to interact with the InfluxDB container (health check, REST API, etc.)
50+
"""
51+
host = self.get_container_host_ip()
52+
port = self.get_exposed_port(self.container_port)
53+
54+
return f"http://{host}:{port}"
55+
56+
@wait_container_is_ready(ConnectionError, ReadTimeout)
57+
def _health_check(self) -> dict:
58+
"""
59+
Performs a health check on the running InfluxDB container.
60+
The call is retried until it works thanks to the @wait_container_is_ready decorator.
61+
See its documentation for the max number of retries or the timeout.
62+
"""
63+
64+
url = self.get_url()
65+
response = get(f"{url}/health", timeout=1)
66+
response.raise_for_status()
67+
68+
return response.json()
69+
70+
def get_influxdb_version(self) -> str:
71+
"""
72+
Returns the version of the InfluxDB service, as returned by the healthcheck.
73+
"""
74+
75+
return self._health_check().get("version")
76+
77+
def start(self) -> "InfluxDbContainer":
78+
"""
79+
Spawns a container of the InfluxDB Docker image, ready to be used.
80+
"""
81+
super().start()
82+
self._health_check()
83+
84+
return self

src/testcontainers/community/influxdb1/__init__.py renamed to src/testcontainers/community/influxdb/version1.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
from influxdb import InfluxDBClient
1717

18-
from testcontainers.community.influxdb import InfluxDbContainer
18+
from .base import InfluxDbContainer
1919

2020

2121
class InfluxDb1Container(InfluxDbContainer):

src/testcontainers/community/influxdb2/__init__.py renamed to src/testcontainers/community/influxdb/version2.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
from influxdb_client import InfluxDBClient, Organization
1818

19-
from testcontainers.community.influxdb import InfluxDbContainer
19+
from .base import InfluxDbContainer
2020

2121

2222
class InfluxDb2Container(InfluxDbContainer):

src/testcontainers/influxdb1.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import warnings
22

3-
from testcontainers.community.influxdb1 import (
3+
from testcontainers.community.influxdb import (
44
InfluxDb1Container,
55
)
66

src/testcontainers/influxdb2.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import warnings
22

3-
from testcontainers.community.influxdb2 import (
3+
from testcontainers.community.influxdb import (
44
InfluxDb2Container,
55
)
66

0 commit comments

Comments
 (0)