From f8e8218169cefb7e2af67660b8d2ef99a82a053e Mon Sep 17 00:00:00 2001 From: Tomer Nosrati Date: Mon, 2 Mar 2026 16:22:17 +0200 Subject: [PATCH 1/2] Make pytest-celery package install configurable in worker Dockerfile Added PYTEST_CELERY_PKG build arg to the worker Dockerfile, defaulting to 'pytest-celery' (PyPI). This allows CI and users to override the install source, e.g. to install from a specific branch: PYTEST_CELERY_PKG='pytest-celery@git+https://github.com/celery/pytest-celery.git@my-branch' - Added PYTEST_CELERY_PKG ARG to Dockerfile (default: pytest-celery) - Added DEFAULT_WORKER_PYTEST_CELERY_PKG constant - Added pytest_celery_pkg() classmethod to CeleryWorkerContainer - Added default_worker_pytest_celery_pkg fixture - Wired into buildargs() and celery_base_worker_image build fixture --- .github/workflows/examples.yml | 3 +++ .github/workflows/python-package.yml | 3 +++ src/pytest_celery/__init__.py | 1 + src/pytest_celery/vendors/worker/Dockerfile | 3 ++- src/pytest_celery/vendors/worker/container.py | 11 +++++++++++ src/pytest_celery/vendors/worker/defaults.py | 1 + src/pytest_celery/vendors/worker/fixtures.py | 14 ++++++++++++++ tests/unit/vendors/test_worker/test_worker.py | 2 ++ 8 files changed, 37 insertions(+), 1 deletion(-) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 078adb68..02cfb893 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -29,6 +29,9 @@ on: permissions: contents: read # to fetch code (actions/checkout) +env: + PYTEST_CELERY_PKG: "pytest-celery@git+https://github.com/${{ github.event.pull_request.head.repo.full_name || github.repository }}.git@${{ github.head_ref || github.ref_name }}" + jobs: celery_bug_report: runs-on: ${{ matrix.os }} diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index 3562ab6b..6790a11a 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -29,6 +29,9 @@ on: permissions: contents: read # to fetch code (actions/checkout) +env: + PYTEST_CELERY_PKG: "pytest-celery@git+https://github.com/${{ github.event.pull_request.head.repo.full_name || github.repository }}.git@${{ github.head_ref || github.ref_name }}" + jobs: Unit: runs-on: ${{ matrix.os }} diff --git a/src/pytest_celery/__init__.py b/src/pytest_celery/__init__.py index b482c512..7a765566 100644 --- a/src/pytest_celery/__init__.py +++ b/src/pytest_celery/__init__.py @@ -115,6 +115,7 @@ from pytest_celery.vendors.worker.fixtures import default_worker_env from pytest_celery.vendors.worker.fixtures import default_worker_initial_content from pytest_celery.vendors.worker.fixtures import default_worker_ports + from pytest_celery.vendors.worker.fixtures import default_worker_pytest_celery_pkg from pytest_celery.vendors.worker.fixtures import default_worker_signals from pytest_celery.vendors.worker.fixtures import default_worker_tasks from pytest_celery.vendors.worker.fixtures import default_worker_utils_module diff --git a/src/pytest_celery/vendors/worker/Dockerfile b/src/pytest_celery/vendors/worker/Dockerfile index 03a95ef7..41561b7d 100644 --- a/src/pytest_celery/vendors/worker/Dockerfile +++ b/src/pytest_celery/vendors/worker/Dockerfile @@ -26,6 +26,7 @@ ARG CELERY_VERSION="" ARG CELERY_LOG_LEVEL=INFO ARG CELERY_WORKER_NAME=celery_test_worker ARG CELERY_WORKER_QUEUE=celery +ARG PYTEST_CELERY_PKG="pytest-celery" ENV WORKER_VERSION=$CELERY_VERSION ENV LOG_LEVEL=$CELERY_LOG_LEVEL ENV WORKER_NAME=$CELERY_WORKER_NAME @@ -40,7 +41,7 @@ EXPOSE 5678 RUN pip install --no-cache-dir --upgrade \ pip \ celery[redis,pymemcache,gevent,sqs]${WORKER_VERSION:+==$WORKER_VERSION} \ - pytest-celery + ${PYTEST_CELERY_PKG} # The workdir must be /app WORKDIR /app diff --git a/src/pytest_celery/vendors/worker/container.py b/src/pytest_celery/vendors/worker/container.py index 61a96359..9c37e2f4 100644 --- a/src/pytest_celery/vendors/worker/container.py +++ b/src/pytest_celery/vendors/worker/container.py @@ -15,6 +15,7 @@ from pytest_celery.vendors.worker.defaults import DEFAULT_WORKER_LOG_LEVEL from pytest_celery.vendors.worker.defaults import DEFAULT_WORKER_NAME from pytest_celery.vendors.worker.defaults import DEFAULT_WORKER_PORTS +from pytest_celery.vendors.worker.defaults import DEFAULT_WORKER_PYTEST_CELERY_PKG from pytest_celery.vendors.worker.defaults import DEFAULT_WORKER_QUEUE from pytest_celery.vendors.worker.defaults import DEFAULT_WORKER_VERSION from pytest_celery.vendors.worker.volume import WorkerInitialContent @@ -140,6 +141,15 @@ def signals_modules(cls) -> set: """ return set() + @classmethod + def pytest_celery_pkg(cls) -> str: + """The pytest-celery package to install in the worker container. + + Returns: + str: pip install spec for pytest-celery. + """ + return DEFAULT_WORKER_PYTEST_CELERY_PKG + @classmethod def buildargs(cls) -> dict: """Build arguments for the built-in worker image.""" @@ -148,6 +158,7 @@ def buildargs(cls) -> dict: "CELERY_LOG_LEVEL": cls.log_level(), "CELERY_WORKER_NAME": cls.worker_name(), "CELERY_WORKER_QUEUE": cls.worker_queue(), + "PYTEST_CELERY_PKG": cls.pytest_celery_pkg(), } @classmethod diff --git a/src/pytest_celery/vendors/worker/defaults.py b/src/pytest_celery/vendors/worker/defaults.py index 087e19c3..e1165863 100644 --- a/src/pytest_celery/vendors/worker/defaults.py +++ b/src/pytest_celery/vendors/worker/defaults.py @@ -37,3 +37,4 @@ DEFAULT_WORKER_QUEUE = WORKER_QUEUE DEFAULT_WORKER_CONTAINER_TIMEOUT = 60 DEFAULT_WORKER_VOLUME = WORKER_VOLUME +DEFAULT_WORKER_PYTEST_CELERY_PKG = os.environ.get("PYTEST_CELERY_PKG", "pytest-celery") diff --git a/src/pytest_celery/vendors/worker/fixtures.py b/src/pytest_celery/vendors/worker/fixtures.py index acdb6d78..4c8dcdf9 100644 --- a/src/pytest_celery/vendors/worker/fixtures.py +++ b/src/pytest_celery/vendors/worker/fixtures.py @@ -103,6 +103,7 @@ def default_worker_container_session_cls() -> type[CeleryWorkerContainer]: "CELERY_LOG_LEVEL": fxtr("default_worker_celery_log_level"), "CELERY_WORKER_NAME": fxtr("default_worker_celery_worker_name"), "CELERY_WORKER_QUEUE": fxtr("default_worker_celery_worker_queue"), + "PYTEST_CELERY_PKG": fxtr("default_worker_pytest_celery_pkg"), }, ) @@ -163,6 +164,19 @@ def default_worker_celery_worker_queue(default_worker_container_session_cls: typ return default_worker_container_session_cls.worker_queue() +@pytest.fixture(scope="session") +def default_worker_pytest_celery_pkg(default_worker_container_session_cls: type[CeleryWorkerContainer]) -> str: + """The pytest-celery package to install in the worker container. + + Args: + default_worker_container_session_cls (type[CeleryWorkerContainer]): See also: :ref:`vendor-class`. + + Returns: + str: pip install spec for pytest-celery. + """ + return default_worker_container_session_cls.pytest_celery_pkg() + + @pytest.fixture def default_worker_command(default_worker_container_cls: type[CeleryWorkerContainer]) -> list[str]: """Command to run the container. diff --git a/tests/unit/vendors/test_worker/test_worker.py b/tests/unit/vendors/test_worker/test_worker.py index 8bb34a57..2182f214 100644 --- a/tests/unit/vendors/test_worker/test_worker.py +++ b/tests/unit/vendors/test_worker/test_worker.py @@ -7,6 +7,7 @@ from pytest_celery import DEFAULT_WORKER_ENV from pytest_celery import DEFAULT_WORKER_LOG_LEVEL from pytest_celery import DEFAULT_WORKER_NAME +from pytest_celery import DEFAULT_WORKER_PYTEST_CELERY_PKG from pytest_celery import DEFAULT_WORKER_QUEUE from pytest_celery import DEFAULT_WORKER_VERSION from pytest_celery import CeleryBackendCluster @@ -46,6 +47,7 @@ def test_buildargs(self): "CELERY_LOG_LEVEL": DEFAULT_WORKER_LOG_LEVEL, "CELERY_WORKER_NAME": DEFAULT_WORKER_NAME, "CELERY_WORKER_QUEUE": DEFAULT_WORKER_QUEUE, + "PYTEST_CELERY_PKG": DEFAULT_WORKER_PYTEST_CELERY_PKG, } class test_celery_worker_container_env: From 34f0886c1155d8bf94f66744d7e8a421591320f6 Mon Sep 17 00:00:00 2001 From: Tomer Nosrati Date: Mon, 2 Mar 2026 17:47:56 +0200 Subject: [PATCH 2/2] Address PR review: quote Dockerfile arg and use commit SHA in CI - Quote ${PYTEST_CELERY_PKG} in Dockerfile to prevent shell word-splitting - Use commit SHA instead of branch name in CI workflows for deterministic builds --- .github/workflows/examples.yml | 2 +- .github/workflows/python-package.yml | 2 +- src/pytest_celery/vendors/worker/Dockerfile | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 02cfb893..59e5bf56 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -30,7 +30,7 @@ permissions: contents: read # to fetch code (actions/checkout) env: - PYTEST_CELERY_PKG: "pytest-celery@git+https://github.com/${{ github.event.pull_request.head.repo.full_name || github.repository }}.git@${{ github.head_ref || github.ref_name }}" + PYTEST_CELERY_PKG: "pytest-celery@git+https://github.com/${{ github.event.pull_request.head.repo.full_name || github.repository }}.git@${{ github.event.pull_request.head.sha || github.sha }}" jobs: celery_bug_report: diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index 6790a11a..a1becb89 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -30,7 +30,7 @@ permissions: contents: read # to fetch code (actions/checkout) env: - PYTEST_CELERY_PKG: "pytest-celery@git+https://github.com/${{ github.event.pull_request.head.repo.full_name || github.repository }}.git@${{ github.head_ref || github.ref_name }}" + PYTEST_CELERY_PKG: "pytest-celery@git+https://github.com/${{ github.event.pull_request.head.repo.full_name || github.repository }}.git@${{ github.event.pull_request.head.sha || github.sha }}" jobs: Unit: diff --git a/src/pytest_celery/vendors/worker/Dockerfile b/src/pytest_celery/vendors/worker/Dockerfile index 41561b7d..0346b3c2 100644 --- a/src/pytest_celery/vendors/worker/Dockerfile +++ b/src/pytest_celery/vendors/worker/Dockerfile @@ -41,7 +41,7 @@ EXPOSE 5678 RUN pip install --no-cache-dir --upgrade \ pip \ celery[redis,pymemcache,gevent,sqs]${WORKER_VERSION:+==$WORKER_VERSION} \ - ${PYTEST_CELERY_PKG} + "${PYTEST_CELERY_PKG}" # The workdir must be /app WORKDIR /app