Skip to content

Commit 3519f4b

Browse files
totallyzenalexanderankinjankatinsmax-pfeiffer
authored
docs(contributing): add contribution and new-container guide (#460)
# change Document how to contribute, with initial focus on making local development smooth. # Tasks - [x] Finish the `new-container` guide - [x] Remove any old docs referring to - [x] Update `README.md` to point at the contribution guide - [x] Update `README.md` to add badges (supported python versions, etc) and to give kudos to current and past maintainers and contributors --------- Co-authored-by: Dave Ankin <[email protected]> Co-authored-by: Jan Katins <[email protected]> Co-authored-by: Max Pfeiffer <[email protected]>
1 parent e711800 commit 3519f4b

File tree

8 files changed

+247
-89
lines changed

8 files changed

+247
-89
lines changed

.github/CONTRIBUTING.md

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# Contributing to `testcontainers-python`
2+
3+
Welcome to the `testcontainers-python` community!
4+
This should give you an idea about how we build, test and release `testcontainers-python`!
5+
6+
Highly recommended to read this document thoroughly to understand what we're working on right now
7+
and what our priorities are before you are trying to contribute something.
8+
9+
This will greatly increase your chances of getting prompt replies as the maintainers are volunteers themselves.
10+
11+
## Before you Begin
12+
13+
We recommend following these steps:
14+
15+
1. Finish reading this document.
16+
2. Read the [recently updated issues][1]
17+
3. Look for existing issues on the subject you are interested in - we do our best to label everything correctly
18+
19+
20+
## Local Development
21+
22+
### Pre-Requisites
23+
24+
You need to have the following tools available to you:
25+
- `make` - You'll need a GNU Make for common developer activities
26+
- `poetry` - This is the primary package manager for the project
27+
- `pyenv` **Recommended**: For installing python versions for your system.
28+
Poetry infers the current latest version from what it can find on the `PATH` so you are still fine if you don't use `pyenv`.
29+
30+
### Build and test
31+
32+
33+
- Run `make install` to get `poetry` to install all dependencies and set up `pre-commit`
34+
- **Recommended**: Run `make` or `make help` to see other commands available to you.
35+
- After this, you should have a working virtual environment and proceed with writing code with your favourite IDE
36+
- **TIP**: You can run `make core/tests` or `make module/<my-module>/tests` to run the tests specifically for that to speed up feedback cycles
37+
- You can also run `make lint` to run the `pre-commit` for the entire codebase.
38+
39+
40+
## Adding new containers
41+
42+
We have an [issue template](.github/ISSUE_TEMPLATE/new-container.md) for adding new containers, please refer to that for more information.
43+
Once you've talked to the maintainers (we do our best to reply!) then you can proceed with contributing the new container.
44+
45+
> [!WARNING]
46+
> PLease raise an issue before you try to contribute a new container! It helps maintainers understand your use-case and motivation.
47+
> This way we can keep pull requests foruced on the "how", not the "why"! :pray:
48+
> It also gives maintainers a chance to give you last-minute guidance on caveats or expectations, particularly with
49+
> new extra dependencies and how to manage them.
50+
51+
52+
## Raising Issues
53+
54+
We have [Issue Templates][2] to cover most cases, please try to adhere to them, they will guide you through the process.
55+
Try to look through the existing issues before you raise a new one.
56+
57+
58+
## Releasing Versions
59+
60+
We have automated Semantic Versioning and release via [release-please](workflows/release-please.yml).
61+
This takes care of:
62+
- Detecting the next version, based on the commits that landed on `main`
63+
- When a Release PR has been merged
64+
- Create a GitHub Release with the CHANGELOG included
65+
- Update the [CHANGELOG](../CHANGELOG.md), similar to the GitHub Release
66+
- Release to PyPI via a [trusted publisher](https://docs.pypi.org/trusted-publishers/using-a-publisher/)
67+
- Automatically script updates in files where it's needed instead of hand-crafting it (i.e. in `pyproject.toml`)
68+
69+
> [!CRITICAL]
70+
> Community modules are supported on a best-effort basis and for maintenance reasons, any change to them
71+
> is only covered under minor and patch changes.
72+
>
73+
> Community modules changes DO NOT contribute to major version changes!
74+
>
75+
> If your community module container was broken by a minor or patch version change, check out the change logs!
76+
77+
# Thank you!
78+
79+
Thanks for reading, feedback on documentation is always welcome!
80+
81+
[1]: https://github.com/testcontainers/testcontainers-python/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc "Recently Updated Issues showing you what we're focusing on"
82+
[2]: https://github.com/testcontainers/testcontainers-python/issues/new/choose "List of current issue templates, please use them"
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
---
2+
name: New Container
3+
about: Tell the Testcontainers-Python team about a container you'd like to have support for.
4+
title: 'New Container: '
5+
labels: '🚀 enhancement'
6+
assignees: ''
7+
8+
---
9+
10+
<!-- feel free to remove any irrelevant section(s) below -->
11+
12+
**What is the new container you'd like to have?**
13+
14+
Please link some docker containers as well as documentation/arguments to the benefits of having this container.
15+
16+
**Why not just use a generic container for this?**
17+
18+
Please describe why the `DockerContainer("my-image:latest")` approach is not useful enough.
19+
20+
Having a dedicated `TestContainer` usually means the need for some or all of these:
21+
- complicated setup/configuration
22+
- the wait strategy is complex for the container, usually more than just an http wait
23+
24+
**Other references:**
25+
26+
Include any other relevant reading material about the enhancement.

.github/ISSUE_TEMPLATE/question.md

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,27 +9,33 @@ assignees: ''
99

1010
<!-- feel free to remove any irrelevant section(s) below -->
1111

12-
**What are you trying to do?**
12+
## What are you trying to do?
1313

1414
Ask your question here
1515

16-
**Where are you trying to do it?**
16+
## Where are you trying to do it?
1717

1818
Provide a self-contained code snippet that illustrates the bug or unexpected behavior.
1919
Ideally, include a link to a public repository with a minimal project where someone from the
2020
testcontainers-python can submit a PR with a solution to the problem you are facing with the library.
2121

22-
**Runtime environment**
22+
## Runtime environment
2323

24-
Provide a summary of your runtime environment. Which operating system, python version, and docker version are you using? What is the version of `testcontainers-python` you are using? You can run the following commands to get the relevant information.
24+
Provide a summary of your runtime environment. Which operating system, python version, and docker version are you using?
25+
What is the version of `testcontainers-python` you are using? You can run the following commands to get the relevant information.
26+
27+
Paste the results of the bash below
28+
29+
```bash
30+
uname -a
31+
echo "------"
32+
docker info
33+
echo "------"
34+
poetry run python --version
35+
echo "------"
36+
poetry show --tree
37+
```
2538

2639
```bash
27-
# Get the operating system information (on a unix os).
28-
$ uname -a
29-
# Get the python version.
30-
$ python --version
31-
# Get the docker version and other docker information.
32-
$ docker info
33-
# Get all python packages.
34-
$ pip freeze
40+
paste-me-here
3541
```
Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,40 @@
1-
You have implemented a new container and would like to contribute it? Great! Here are the necessary steps.
2-
3-
- [ ] Create a new feature directory and populate it with the package structure [described in the documentation](https://testcontainers-python.readthedocs.io/en/latest/#package-structure). Copying one of the existing features is likely the best way to get started.
4-
- [ ] Implement the new feature (typically in `__init__.py`) and corresponding tests.
5-
- [ ] Update the feature `README.rst` and add it to the table of contents (`toctree` directive) in the top-level `README.rst`.
6-
- [ ] Add a line `[feature name]` to the list of components in the GitHub Action workflow in `.github/workflows/main.yml` to run tests, build, and publish your package when pushed to the `main` branch.
7-
- [ ] Rebase your development branch on `main` (or merge `main` into your development branch).
8-
- [ ] Add a line `-e file:[feature name]` to `requirements.in` and open a pull request. Opening a pull request will automatically generate lock files to ensure reproducible builds (see the [pip-tools documentation](https://pip-tools.readthedocs.io/en/latest/) for details). Finally, run `python get_requirements.py --pr=[your PR number]` to fetch the updated requirement files (the build needs to have succeeded).
1+
# New Container
2+
3+
<!-- You have implemented a new container and would like to contribute it? Great! Here are the necessary checklist steps. -->
4+
5+
Fixes ...
6+
7+
<!--
8+
Please do not raise a PR for new container without having raised an issue first.
9+
It helps reduce unnecessary work for you and the maintainers!
10+
-->
11+
12+
13+
# PR Checklist
14+
15+
- [ ] Your PR title follows the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) syntax
16+
as we make use of this for detecting Semantic Versioning changes.
17+
- [ ] Your PR allows maintainers to edit your branch, this will speed up resolving minor issues!
18+
- [ ] The new container is implemented under `modules/*`
19+
- Your module follows [PEP 420](https://peps.python.org/pep-0420/) with implicit namespace packages
20+
(if unsure, look at other existing community modules)
21+
- Your package namespacing follows `testcontainers.<modulename>.*`
22+
and you DO NOT have an `__init__.py` above your module's level.
23+
- Your module has it's own tests under `modules/*/tests`
24+
- Your module has a `README.rst` and hooks in the `.. auto-class` and `.. title` of your container
25+
- Implement the new feature (typically in `__init__.py`) and corresponding tests.
26+
- [ ] Your module is added in `pyproject.toml`
27+
- it is declared under `tool.poetry.packages` - see other community modules
28+
- it is declared under `tool.poetry.extras` with the same name as your module name,
29+
we still prefer adding _NO EXTRA DEPENDENCIES_, meaning `mymodule = []` is the preferred addition
30+
(see the notes at the bottom)
31+
- [ ] The `INDEX.rst` at the project root includes your module under the `.. toctree` directive
32+
- [ ] Your branch is up to date (or we'll use GH's "update branch" function through the UI)
33+
34+
# Preferred implementation
35+
36+
- The current consensus among maintainers is to try to avoid enforcing the client library
37+
for the given tools you are triyng to implement.
38+
- This means we want you to avoid adding specific libraries as dependencies to `testcontainers`.
39+
- Therefore, you should implement the configuration and the waiting with as little extra as possible
40+
- You may still find it useful to add your preferred client library as a dev dependency

Dockerfile

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
1-
ARG version=3.8
2-
FROM python:${version}
1+
ARG PYTHON_VERSION
2+
FROM python:${version}-slim-bookworm
33

44
WORKDIR /workspace
55
RUN pip install --upgrade pip \
66
&& apt-get update \
77
&& apt-get install -y \
88
freetds-dev \
99
&& rm -rf /var/lib/apt/lists/*
10+
11+
# install requirements we exported from poetry
1012
COPY build/requirements.txt requirements.txt
11-
COPY setup.py README.rst ./
1213
RUN pip install -r requirements.txt
14+
15+
# copy project source
1316
COPY . .

Makefile

Lines changed: 45 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,78 @@
1-
PYTHON_VERSIONS = 3.9 3.10 3.11
1+
.DEFAULT_GOAL := help
2+
3+
24
PYTHON_VERSION ?= 3.10
35
IMAGE = testcontainers-python:${PYTHON_VERSION}
4-
RUN = docker run --rm -it
5-
# Get all directories that contain a setup.py and get the directory name.
66
PACKAGES = core $(addprefix modules/,$(notdir $(wildcard modules/*)))
77

8-
# All */dist folders for each of the packages.
9-
DISTRIBUTIONS = $(addsuffix /dist,${PACKAGES})
108
UPLOAD = $(addsuffix /upload,${PACKAGES})
11-
# All */tests folders for each of the test suites.
129
TESTS = $(addsuffix /tests,$(filter-out meta,${PACKAGES}))
1310
TESTS_DIND = $(addsuffix -dind,${TESTS})
1411
DOCTESTS = $(addsuffix /doctests,$(filter-out modules/README.md,${PACKAGES}))
15-
# All linting targets.
16-
LINT = $(addsuffix /lint,${PACKAGES})
17-
18-
# Targets to build a distribution for each package.
19-
dist: ${DISTRIBUTIONS}
20-
${DISTRIBUTIONS} : %/dist : %/setup.py
21-
cd $* \
22-
&& python setup.py bdist_wheel \
23-
&& twine check dist/*
24-
25-
# Targets to run the test suite for each package.
26-
tests : ${TESTS}
27-
${TESTS} : %/tests :
12+
13+
14+
install: ## Set up the project for development
15+
poetry install --all-extras
16+
poetry run pre-commit install
17+
18+
build: ## Build the python package
19+
poetry build && poetry run twine check dist/*
20+
21+
tests: ${TESTS} ## Run tests for each package
22+
${TESTS}: %/tests:
2823
poetry run pytest -v --cov=testcontainers.$* $*/tests
2924

30-
# Target to combine and report coverage.
31-
coverage:
25+
coverage: ## Target to combine and report coverage.
3226
poetry run coverage combine
3327
poetry run coverage report
3428
poetry run coverage xml
3529
poetry run coverage html
3630

37-
# Target to lint the code.
38-
lint:
39-
pre-commit run -a
40-
41-
# Targets to publish packages.
42-
upload : ${UPLOAD}
43-
${UPLOAD} : %/upload :
44-
if [ ${TWINE_REPOSITORY}-$* = testpypi-meta ]; then \
45-
echo "Cannot upload meta package to testpypi because of missing permissions."; \
46-
else \
47-
twine upload --non-interactive --skip-existing $*/dist/*; \
48-
fi
49-
50-
# Targets to build docker images
51-
image:
31+
lint: ## Lint all files in the project, which we also run in pre-commit
32+
poetry run pre-commit run -a
33+
34+
image: ## Make the docker image for dind tests
5235
poetry export -f requirements.txt -o build/requirements.txt
53-
docker build --build-arg version=${PYTHON_VERSION} -t ${IMAGE} .
36+
docker build --build-arg PYTHON_VERSION=${PYTHON_VERSION} -t ${IMAGE} .
5437

55-
# Targets to run tests in docker containers
56-
tests-dind : ${TESTS_DIND}
38+
DOCKER_RUN = docker run --rm -v /var/run/docker.sock:/var/run/docker.sock
5739

58-
${TESTS_DIND} : %/tests-dind : image
59-
${RUN} -v /var/run/docker.sock:/var/run/docker.sock ${IMAGE} \
60-
bash -c "make $*/lint $*/tests"
40+
tests-dind: ${TESTS_DIND} ## Run the tests in docker containers to test `dind`
41+
${TESTS_DIND}: %/tests-dind: image
42+
${DOCKER_RUN} ${IMAGE} \
43+
bash -c "make $*/tests"
6144

62-
# Target to build the documentation
63-
docs :
45+
docs: ## Build the docs for the project
6446
poetry run sphinx-build -nW . docs/_build
6547

6648
# Target to build docs watching for changes as per https://stackoverflow.com/a/21389615
6749
docs-watch :
6850
poetry run sphinx-autobuild . docs/_build # requires 'pip install sphinx-autobuild'
6951

70-
doctests : ${DOCTESTS}
52+
doctests: ${DOCTESTS} ## Run doctests found across the documentation.
7153
poetry run sphinx-build -b doctest . docs/_build
7254

73-
${DOCTESTS} : %/doctests :
55+
${DOCTESTS}: %/doctests: ## Run doctests found for a module.
7456
poetry run sphinx-build -b doctest -c doctests $* docs/_build
7557

76-
# Remove any generated files.
77-
clean :
58+
59+
clean: ## Remove generated files.
7860
rm -rf docs/_build
79-
rm -rf */build
80-
rm -rf */dist
61+
rm -rf build
62+
rm -rf dist
8163
rm -rf */*.egg-info
8264

65+
clean-all: clean ## Remove all generated files and reset the local virtual environment
66+
rm -rf .venv
67+
8368
# Targets that do not generate file-level artifacts.
84-
.PHONY : clean dists ${DISTRIBUTIONS} docs doctests image tests ${TESTS}
69+
.PHONY: clean docs doctests image tests ${TESTS}
70+
71+
72+
# Implements this pattern for autodocumenting Makefiles:
73+
# https://marmelab.com/blog/2016/02/29/auto-documented-makefile.html
74+
#
75+
# Picks up all comments that start with a ## and are at the end of a target definition line.
76+
.PHONY: help
77+
help: ## Display command usage
78+
@grep -E '^[0-9a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'

README.md

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
1+
[![Poetry](https://img.shields.io/endpoint?url=https://python-poetry.org/badge/v0.json)](https://python-poetry.org/)
12
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
2-
[![image](https://img.shields.io/pypi/v/testcontainers.svg)](https://pypi.python.org/pypi/testcontainers)
3-
[![image](https://img.shields.io/pypi/l/testcontainers.svg)](https://github.com/testcontainers/testcontainers-python/blob/main/LICENSE)
4-
[![image](https://img.shields.io/pypi/pyversions/testcontainers.svg)](https://pypi.python.org/pypi/testcontainers)
3+
![PyPI - Version](https://img.shields.io/pypi/v/testcontainers)
4+
[![PyPI - License](https://img.shields.io/pypi/l/testcontainers.svg)](https://github.com/testcontainers/testcontainers-python/blob/main/LICENSE)
5+
[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/testcontainers.svg)](https://pypi.python.org/pypi/testcontainers)
56
[![codecov](https://codecov.io/gh/testcontainers/testcontainers-python/branch/master/graph/badge.svg)](https://codecov.io/gh/testcontainers/testcontainers-python)
7+
![Core Tests](https://github.com/testcontainers/testcontainers-python/actions/workflows/ci-core.yml/badge.svg)
8+
![Community Tests](https://github.com/testcontainers/testcontainers-python/actions/workflows/ci-community.yml/badge.svg)
9+
[![Docs](https://readthedocs.org/projects/testcontainers-python/badge/?version=latest)](http://testcontainers-python.readthedocs.io/en/latest/?badge=latest)
610

11+
[![Codespace](https://github.com/codespaces/badge.svg)](https://codespaces.new/testcontainers/testcontainers-python)
712

813
# Testcontainers Python
914

@@ -30,6 +35,10 @@ For more information, see [the docs][readthedocs].
3035

3136
The snippet above will spin up a postgres database in a container. The `get_connection_url()` convenience method returns a `sqlalchemy` compatible url we use to connect to the database and retrieve the database version.
3237

38+
## Contributing / Development / Release
39+
40+
See [CONTRIBUTING.md](.github/CONTRIBUTING.md) for more details.
41+
3342
## Configuration
3443

3544
| Env Variable | Example | Description |

0 commit comments

Comments
 (0)