diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8ab73cdb..5d69e491 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -3,7 +3,7 @@ variables: TUTOR_IMAGES: ecommerce ecommerce-worker orders-dev payment-dev TUTOR_PYPI_PACKAGE: tutor-ecommerce TUTOR_EXTRA_ENABLED_PLUGINS: discovery mfe - OPENEDX_RELEASE: olive + OPENEDX_RELEASE: palm GITHUB_REPO: overhangio/tutor-ecommerce include: diff --git a/setup.py b/setup.py index 840481f7..53f3de15 100644 --- a/setup.py +++ b/setup.py @@ -32,11 +32,11 @@ long_description=readme, packages=find_packages(exclude=["tests*"]), include_package_data=True, - python_requires=">=3.7", + python_requires=">=3.8", install_requires=[ - "tutor>=15.0.0,<16.0.0", - "tutor-discovery>=15.0.0,<16.0.0", - "tutor-mfe>=15.0.0,<16.0.0", + "tutor>=16.0.0,<17.0.0", + "tutor-discovery>=16.0.0,<17.0.0", + "tutor-mfe>=16.0.0,<17.0.0", ], extras_require={"dev": ["scriv"]}, entry_points={"tutor.plugin.v1": ["ecommerce = tutorecommerce.plugin"]}, @@ -46,9 +46,9 @@ "License :: OSI Approved :: GNU Affero General Public License v3", "Operating System :: OS Independent", "Programming Language :: Python", - "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", ], ) diff --git a/tutorecommerce/__about__.py b/tutorecommerce/__about__.py index 7587e77c..60b692a2 100644 --- a/tutorecommerce/__about__.py +++ b/tutorecommerce/__about__.py @@ -1,4 +1,4 @@ -__version__ = "15.0.2" +__version__ = "16.0.0" # Handle version suffix for nightly, just like tutor core. __version_suffix__ = "" diff --git a/tutorecommerce/patches/local-docker-compose-services b/tutorecommerce/patches/local-docker-compose-services index 917c9af7..7612a4d9 100644 --- a/tutorecommerce/patches/local-docker-compose-services +++ b/tutorecommerce/patches/local-docker-compose-services @@ -7,8 +7,8 @@ ecommerce: - ../plugins/ecommerce/apps/ecommerce/settings:/openedx/ecommerce/ecommerce/settings/tutor:ro depends_on: - discovery + - lms {% if RUN_MYSQL %}- mysql{% endif %} - {% if RUN_LMS %}- lms{% endif %} ecommerce-worker: image: {{ ECOMMERCE_WORKER_DOCKER_IMAGE }} diff --git a/tutorecommerce/plugin.py b/tutorecommerce/plugin.py index 38eda710..0f2b8fa7 100644 --- a/tutorecommerce/plugin.py +++ b/tutorecommerce/plugin.py @@ -1,9 +1,13 @@ +from __future__ import annotations + from glob import glob import os import pkg_resources +import typing as t from tutor import hooks as tutor_hooks +from tutormfe.plugin import MFE_APPS, MFE_ATTRS_TYPE from .__about__ import __version__ @@ -78,6 +82,24 @@ }, } + +@MFE_APPS.add() +def _add_ecommerce_mfe_apps(apps: dict[str, MFE_ATTRS_TYPE]) -> dict[str, MFE_ATTRS_TYPE]: + apps.update( + { + "orders": { + "repository": "https://github.com/edx/frontend-app-ecommerce", + "port": 1996, + }, + "payment": { + "repository": "https://github.com/edx/frontend-app-payment", + "port": 1998, + }, + } + ) + return apps + + # Initialization hooks for service in ("mysql", "lms", "ecommerce"): with open( @@ -149,9 +171,7 @@ ####### Boilerplate code # Add the "templates" folder as a template root -tutor_hooks.Filters.ENV_TEMPLATE_ROOTS.add_item( - pkg_resources.resource_filename("tutorecommerce", "templates") -) +tutor_hooks.Filters.ENV_TEMPLATE_ROOTS.add_item(pkg_resources.resource_filename("tutorecommerce", "templates")) # Render the "build" and "apps" folders tutor_hooks.Filters.ENV_TEMPLATE_TARGETS.add_items( [ @@ -167,9 +187,7 @@ ) ): with open(path, encoding="utf-8") as patch_file: - tutor_hooks.Filters.ENV_PATCHES.add_item( - (os.path.basename(path), patch_file.read()) - ) + tutor_hooks.Filters.ENV_PATCHES.add_item((os.path.basename(path), patch_file.read())) # Add configuration entries tutor_hooks.Filters.CONFIG_DEFAULTS.add_items( [(f"ECOMMERCE_{key}", value) for key, value in config.get("defaults", {}).items()] @@ -177,6 +195,36 @@ tutor_hooks.Filters.CONFIG_UNIQUE.add_items( [(f"ECOMMERCE_{key}", value) for key, value in config.get("unique", {}).items()] ) -tutor_hooks.Filters.CONFIG_OVERRIDES.add_items( - list(config.get("overrides", {}).items()) -) +tutor_hooks.Filters.CONFIG_OVERRIDES.add_items(list(config.get("overrides", {}).items())) + + +@tutor_hooks.Filters.APP_PUBLIC_HOSTS.add() +def _print_ecommerce_public_hosts(hosts: list[str], context_name: t.Literal["local", "dev"]) -> list[str]: + if context_name == "dev": + hosts += ["{{ ECOMMERCE_HOST }}:8130"] + else: + hosts += ["{{ ECOMMERCE_HOST }}"] + return hosts + + +REPO_NAME = "ecommerce" + + +# Automount /openedx/ecommerce folder from the container +@tutor_hooks.Filters.COMPOSE_MOUNTS.add() +def _mount_ecommerce_apps(mounts, path_basename): + if path_basename == REPO_NAME: + app_name = REPO_NAME + mounts += [(app_name, "/openedx/ecommerce")] + return mounts + + +# Bind-mount repo at build-time, both for prod and dev images +@tutor_hooks.Filters.IMAGES_BUILD_MOUNTS.add() +def _mount_ecommerce_on_build(mounts: list[tuple[str, str]], host_path: str) -> list[tuple[str, str]]: + path_basename = os.path.basename(host_path) + if path_basename == REPO_NAME: + app_name = REPO_NAME + mounts.append((app_name, f"{app_name}-src")) + mounts.append((f"{app_name}-dev", f"{app_name}-src")) + return mounts diff --git a/tutorecommerce/templates/ecommerce/apps/ecommerce/settings/partials/common.py b/tutorecommerce/templates/ecommerce/apps/ecommerce/settings/partials/common.py index e7b4a946..1ca4b389 100644 --- a/tutorecommerce/templates/ecommerce/apps/ecommerce/settings/partials/common.py +++ b/tutorecommerce/templates/ecommerce/apps/ecommerce/settings/partials/common.py @@ -91,6 +91,8 @@ PAYMENT_PROCESSOR_CONFIG = { "openedx": common_payment_processor_config, "dev": common_payment_processor_config, + "edx" : common_payment_processor_config, + "other" : common_payment_processor_config, } PAYMENT_PROCESSORS = list(PAYMENT_PROCESSORS) + {{ ECOMMERCE_EXTRA_PAYMENT_PROCESSOR_CLASSES }} diff --git a/tutorecommerce/templates/ecommerce/build/ecommerce-worker/Dockerfile b/tutorecommerce/templates/ecommerce/build/ecommerce-worker/Dockerfile index 99fec839..0c764a97 100644 --- a/tutorecommerce/templates/ecommerce/build/ecommerce-worker/Dockerfile +++ b/tutorecommerce/templates/ecommerce/build/ecommerce-worker/Dockerfile @@ -1,7 +1,11 @@ -FROM docker.io/ubuntu:20.04 +{% if is_buildkit_enabled() %}# syntax=docker/dockerfile:1.4{% endif %} +###### Minimal image with base system requirements for most stages +FROM docker.io/ubuntu:20.04 as minimal -RUN apt update && \ - apt install -y git-core language-pack-en python3 python3-pip python3-venv +RUN {% if is_buildkit_enabled() %}--mount=type=cache,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,target=/var/lib/apt,sharing=locked{% endif %} \ + apt update && \ + apt install -y git-core language-pack-en python3 python3-pip python3-venv ARG APP_USER_ID=1000 RUN useradd --home-dir /openedx --create-home --shell /bin/bash --uid ${APP_USER_ID} app @@ -14,8 +18,12 @@ WORKDIR /openedx/ecommerce_worker # Install python venv RUN python3 -m venv ../venv/ ENV PATH "/openedx/venv/bin:$PATH" -RUN pip install setuptools==62.1.0 pip==22.0.4 wheel==0.37.1 -RUN pip install -r requirements/production.txt +RUN {% if is_buildkit_enabled() %}--mount=type=cache,target=/openedx/.cache/pip,sharing=shared {% endif %}pip install \ + # https://pypi.org/project/setuptools/ + # https://pypi.org/project/pip/ + # https://pypi.org/project/wheel/ + setuptools==67.7.2 pip==23.1.2. wheel==0.40.0 +RUN {% if is_buildkit_enabled() %}--mount=type=cache,target=/openedx/.cache/pip,sharing=shared {% endif %}pip install -r requirements/production.txt ENV WORKER_CONFIGURATION_MODULE ecommerce_worker.settings.production CMD celery worker --app=ecommerce_worker.celery_app:app --loglevel=info --maxtasksperchild 100 --queue=fulfillment,email_marketing diff --git a/tutorecommerce/templates/ecommerce/build/ecommerce/Dockerfile b/tutorecommerce/templates/ecommerce/build/ecommerce/Dockerfile index 1f39b2ef..1e1ba966 100644 --- a/tutorecommerce/templates/ecommerce/build/ecommerce/Dockerfile +++ b/tutorecommerce/templates/ecommerce/build/ecommerce/Dockerfile @@ -1,29 +1,35 @@ -FROM docker.io/ubuntu:20.04 +{% if is_buildkit_enabled() %}# syntax=docker/dockerfile:1.4{% endif %} +###### Minimal image with base system requirements for most stages +FROM docker.io/ubuntu:20.04 as minimal -RUN apt update && \ - apt install -y curl git-core language-pack-en libmysqlclient-dev libssl-dev python3 python3-pip python3-venv +RUN {% if is_buildkit_enabled() %}--mount=type=cache,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,target=/var/lib/apt,sharing=locked{% endif %} \ + apt update && \ + apt install -y curl git-core language-pack-en libmysqlclient-dev libssl-dev python3 python3-pip python3-venv ARG APP_USER_ID=1000 +RUN if [ "$APP_USER_ID" = 0 ]; then echo "app user may not be root" && false; fi RUN useradd --home-dir /openedx --create-home --shell /bin/bash --uid ${APP_USER_ID} app USER ${APP_USER_ID} # Create python venv RUN python3 -m venv /openedx/venv/ ENV PATH "/openedx/venv/bin:$PATH" -# https://pypi.org/project/setuptools/ -# https://pypi.org/project/pip/ -# https://pypi.org/project/wheel/ -RUN pip install setuptools==65.5.1 pip==22.3.1. wheel==0.38.4 +RUN {% if is_buildkit_enabled() %}--mount=type=cache,target=/openedx/.cache/pip,sharing=shared {% endif %}pip install \ + # https://pypi.org/project/setuptools/ + # https://pypi.org/project/pip/ + # https://pypi.org/project/wheel/ + setuptools==67.7.2 pip==23.1.2. wheel==0.40.0 # Install a recent version of nodejs # https://pypi.org/project/nodeenv RUN pip install nodeenv==1.7.0 -RUN nodeenv /openedx/nodeenv --node=16.14.2 --prebuilt +RUN nodeenv /openedx/nodeenv --node=16.20.0 --prebuilt ENV PATH /openedx/nodeenv/bin:${PATH} # Install ecommerce ARG ECOMMERCE_REPOSITORY=https://github.com/edx/ecommerce.git -ARG ECOMMERCE_VERSION={{ OPENEDX_COMMON_VERSION }} +ARG ECOMMERCE_VERSION='{{ OPENEDX_COMMON_VERSION }}' RUN mkdir -p /openedx/ecommerce && \ git clone $ECOMMERCE_REPOSITORY --branch $ECOMMERCE_VERSION --depth 1 /openedx/ecommerce WORKDIR /openedx/ecommerce @@ -32,15 +38,15 @@ WORKDIR /openedx/ecommerce RUN git config --global user.email "tutor@overhang.io" \ && git config --global user.name "Tutor" -# nodejs requirements (aka: "make requirements.js") -ARG NPM_REGISTRY={{ NPM_REGISTRY }} -RUN npm install --verbose --registry=$NPM_REGISTRY -RUN ./node_modules/.bin/bower install --allow-root +# Install npm, bower requirements +ARG NPM_REGISTRY='{{ NPM_REGISTRY }}' +RUN {% if is_buildkit_enabled() %}--mount=type=cache,target=/openedx/.npm/,sharing=shared,uid=${APP_USER_ID} {% endif %}npm clean-install --verbose --no-audit --registry=$NPM_REGISTRY +RUN {% if is_buildkit_enabled() %}--mount=type=cache,target=/openedx/.cache/bower,sharing=shared,uid=${APP_USER_ID} {% endif %}./node_modules/.bin/bower install --allow-root # python requirements -RUN pip install -r requirements.txt +RUN {% if is_buildkit_enabled() %}--mount=type=cache,target=/openedx/.cache/pip,sharing=shared {% endif %}pip install -r requirements.txt # https://pypi.org/project/uWSGI/ -RUN pip install uwsgi==2.0.21 +RUN {% if is_buildkit_enabled() %}--mount=type=cache,target=/openedx/.cache/pip,sharing=shared {% endif %}pip install uwsgi==2.0.21 # Install private requirements: this is useful for installing custom payment processors. COPY --chown=app:app ./requirements/ /openedx/requirements @@ -48,7 +54,7 @@ RUN cd /openedx/requirements/ \ && touch ./private.txt \ && pip install -r ./private.txt -{% for extra_requirement in ECOMMERCE_EXTRA_PIP_REQUIREMENTS %}RUN pip install {{ extra_requirement }} +{% for extra_requirement in ECOMMERCE_EXTRA_PIP_REQUIREMENTS %}RUN {% if is_buildkit_enabled() %}--mount=type=cache,target=/openedx/.cache/pip,sharing=shared {% endif %}pip install '{{ extra_requirement }}' {% endfor %} # Collect static assets (aka: "make static")