From 7afc0dbfccfe6b7678cce2d6a9f7f7ececff193f Mon Sep 17 00:00:00 2001
From: Pierre Smeyers <pierre.smeyers@gmail.com>
Date: Fri, 4 Feb 2022 17:06:58 +0100
Subject: [PATCH] feat: add Pipenv support

---
 README.md                      | 26 +++++++++++---------------
 templates/gitlab-ci-python.yml | 28 ++++++++++++++++++++++++----
 2 files changed, 35 insertions(+), 19 deletions(-)

diff --git a/README.md b/README.md
index 9ac3e06..112e2fc 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
 
 This project implements a generic GitLab CI template for [Python](https://www.python.org/).
 
-It provides several features, usable in different modes (by configuration) following those [recommendations](to-be-continuous.gitlab.io/doc/usage/)
+It provides several features, usable in different modes (by configuration).
 
 ## Usage
 
@@ -34,23 +34,19 @@ The cache policy also makes the necessary to manage pip cache (not to download P
 
 ## Multi build-system support
 
-The Python template supports 3 popular dependency management & build systems:
+The Python template supports the most popular dependency management & build systems.
 
-* [Setuptools](https://setuptools.pypa.io/),
-* [Poetry](https://python-poetry.org/),
-* [Requirements Files](https://pip.pypa.io/en/stable/user_guide/#requirements-files) (dependency management only).
+By default it tries to auto-detect the build system used by the project (based on the presence of `pyproject.toml` 
+and/or `setup.py` and/or `requirements.txt`), but the build system might also be set explicitly using the 
+`$PYTHON_BUILD_SYSTEM` variable:
 
-By default the template tries to auto-detect the build system used by the project (based on presence of `pyproject.toml` 
-and/or `setup.py` and/or `requirements.txt`), but the build system might also be explicitly set using the `$PYTHON_BUILD_SYSTEM` variable.
-
-Supported values of `$PYTHON_BUILD_SYSTEM`:
-
-| Value            | Description                                                |
+| Value            | Build System (scope)                                       |
 | ---------------- | ---------------------------------------------------------- |
-| _none_ (default) | The template tries to auto-detect the actual build system, based of the presence of some key files |
-| `setuptools`     | [Setuptools](https://setuptools.pypa.io/) will be used to install dependencies, build and package the project |
-| `poetry`         | [Poetry](https://python-poetry.org/) will be used to install dependencies, build, test and package the project |
-| `reqfile`        | [Requirements Files](https://pip.pypa.io/en/stable/user_guide/#requirements-files) will be used to install dependencies |
+| _none_ (default) | The template tries to **auto-detect** the actual build system |
+| `setuptools`     | [Setuptools](https://setuptools.pypa.io/) (dependencies, build & packaging) |
+| `poetry`         | [Poetry](https://python-poetry.org/) (dependencies, build, test & packaging) |
+| `pipenv`         | [Pipenv](https://pipenv.pypa.io/) (dependencies only) |
+| `reqfile`        | [Requirements Files](https://pip.pypa.io/en/stable/user_guide/#requirements-files) (dependencies only) |
 
 ## Jobs
 
diff --git a/templates/gitlab-ci-python.yml b/templates/gitlab-ci-python.yml
index 26ef1f2..434b958 100644
--- a/templates/gitlab-ci-python.yml
+++ b/templates/gitlab-ci-python.yml
@@ -20,6 +20,7 @@ variables:
   # Poetry support: force virtualenv not in project dir & use local cache dir
   POETRY_CACHE_DIR: "$CI_PROJECT_DIR/.cache/poetry"
   POETRY_VIRTUALENVS_IN_PROJECT: "false"
+  PIPENV_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pipenv"
 
   PYTHON_IMAGE: python:3
   # Default Python project root directory
@@ -224,6 +225,10 @@ variables:
         log_info "--- Build system explictly declared: Setuptools"
         return
         ;;
+      pipenv)
+        log_info "--- Build system explictly declared: Pipenv"
+        return
+        ;;
       reqfile)
         log_info "--- Build system explictly declared: requirements file"
         return
@@ -264,6 +269,10 @@ variables:
     then
       log_info "--- Build system auto-detected: Setuptools (legacy)"
       export PYTHON_BUILD_SYSTEM="setuptools"
+    elif [[ -f "Pipfile" ]]
+    then
+      log_info "--- Build system auto-detected: Pipenv"
+      export PYTHON_BUILD_SYSTEM="pipenv"
     elif [[ -f "${REQUIREMENTS_FILE}" ]]
     then
       log_info "--- Build system auto-detected: requirements file"
@@ -291,6 +300,16 @@ variables:
       # shellcheck disable=SC2086
       pip install ${PIP_OPTS} ".${PYTHON_EXTRA_DEPS:+[$PYTHON_EXTRA_DEPS]}"
       ;;
+    pipenv)
+      # shellcheck disable=SC2086
+      pip install ${PIP_OPTS} pipenv
+      if  [[ ! -f "Pipfile.lock" ]]; then
+        log_warn "Using Pipenv but \\e[33;1mPipfile.lock\\e[0m file not found: you shall commit it with your project files"
+        pipenv install --dev --system
+      else
+        pipenv sync --dev --system
+      fi
+      ;;
     reqfile)
       if [[ -f "${REQUIREMENTS_FILE}" ]]; then
         log_info "--- installing build requirements from \\e[33;1m${REQUIREMENTS_FILE}\\e[0m"
@@ -340,8 +359,8 @@ variables:
       pip install ${PIP_OPTS} setuptools build
       python -m build
       ;;
-    reqfile)
-      log_error "--- packaging is unsupported with requirements build system: read template doc"
+    *)
+      log_error "--- packaging is unsupported with $PYTHON_BUILD_SYSTEM build system: read template doc"
       exit 1
       ;;
     esac
@@ -361,8 +380,8 @@ variables:
       twine upload --verbose dist/*.tar.gz
       twine upload --verbose dist/*.whl
       ;;
-    reqfile)
-      log_error "--- publish is unsupported with requirements build system: read template doc"
+    *)
+      log_error "--- publish is unsupported with $PYTHON_BUILD_SYSTEM build system: read template doc"
       exit 1
       ;;
     esac
@@ -435,6 +454,7 @@ variables:
     paths:
       - ${PIP_CACHE_DIR}
       - ${POETRY_CACHE_DIR}
+      - ${PIPENV_CACHE_DIR}
   before_script:
     - *python-scripts
     - install_ca_certs "${CUSTOM_CA_CERTS:-$DEFAULT_CA_CERTS}"
-- 
GitLab