From a45db53855b9827309e864df891acbc8c7a7dedb Mon Sep 17 00:00:00 2001
From: Daniel Dehennin <daniel.dehennin@ac-dijon.fr>
Date: Mon, 21 Mar 2022 16:42:14 +0100
Subject: [PATCH] feat(python): use `build` module to support PEP517 package
 building

This permit to support either `pyproject.toml or `setup.py` based
projects.

The best way to build is to use `.python:build` which create the
`sdist` and build the `wheel` from it.
---
 templates/Python.yaml | 145 ++++++++++++++++++++++++++++++++++--------
 1 file changed, 117 insertions(+), 28 deletions(-)

diff --git a/templates/Python.yaml b/templates/Python.yaml
index 1d4b93c..9279696 100644
--- a/templates/Python.yaml
+++ b/templates/Python.yaml
@@ -5,6 +5,12 @@
 #
 # - `.python:black:check`: verify formatting of code with `black`
 #
+# - `.python:build`: build the `sdist` and `wheel` packages
+#
+# - `.python:build:sdist`: build the `sdist` package
+#
+# - `.python:build:wheel`: build the `wheel` package
+#
 ---
 #
 # .python:black:check
@@ -57,11 +63,75 @@
     - echo -e "\e[0Ksection_end:`date +%s`:python-black\r\e[0K"
 
 
+#
+# .python:build
+# =============
+#
+# Build the python `sdist` and `wheel` packages with the `build` module
+#
+# USAGE
+# =====
+#
+# include:
+#   - project: EOLE/Infra/ci-tools
+#     ref: stable
+#     file: /templates/Python.yaml
+#
+# stages:
+#   - build
+#
+# python:build {extends: '.python:build'}
+#
+# REQUIREMENTS
+# ============
+#
+# - a `build` stage must be present in your pipeline or it must be
+#   overriden by the extending job to feet your need
+#
+# - the `.rules-map` rules templates
+#
+# - a `pyproject.toml` or `setup.py` file
+#
+# OPTIONAL VARIABLES
+# ==================
+#
+# - `PYTHON_DIST_FILES`: files to upload, defaults to `dist/*'
+#
+# - `PYTHON_SOURCE_DIR`: top level directory of python source where to
+#   find `pyproject.toml` or `setup.py`, defaults to `.'
+#
+# - `PYTHON_BUILD_OPTS`: additional options to pass to the
+#   `pyproject-build` command line
+#
+# - `PYTHON_IMAGE`: name of the python docker image to use
+#
+# SEE ALSO
+# ========
+#
+# - https://pypi.org/project/build/
+#
+.python:build:
+  stage: build
+  extends: .python:base
+  variables:
+    PYTHON_DIST_FILES: dist/*
+  artifacts:
+    paths:
+      - ${PYTHON_SOURCE_DIR}/${PYTHON_DIST_FILES}
+  script:
+    - echo -e "\e[0Ksection_start:`date +%s`:python-build-deps[collapsed=true]\r\e[0KInstall 'build' module"
+    - pip install build
+    - echo -e "\e[0Ksection_end:`date +%s`:python-build-deps\r\e[0K"
+    - echo -e "\e[0Ksection_start:`date +%s`:python-build\r\e[0KBuild distribution `sdist` and `wheel` from '${PYTHON_SOURCE_DIR}'"
+    - pyproject-build ${PYTHON_BUILD_OPTS} "${PYTHON_SOURCE_DIR}"
+    - echo -e "\e[0Ksection_end:`date +%s`:python-build\r\e[0K"
+
+
 #
 # .python:build:sdist
 # ===================
 #
-# Build the python source `.tar.gz`
+# Build the python source `.tar.gz` with the `build` module
 #
 # USAGE
 # =====
@@ -82,9 +152,9 @@
 # - a `build` stage must be present in your pipeline or it must be
 #   overriden by the extending job to feet your need
 #
-# - the `.on-release-tag` rules templates
+# - the `.rules-map` rules templates
 #
-# - a `setup.py` file
+# - a `pyproject.toml` or `setup.py` file
 #
 # OPTIONAL VARIABLES
 # ==================
@@ -92,25 +162,28 @@
 # - `PYTHON_DIST_FILES`: files to upload, defaults to `dist/*.tar.gz'
 #
 # - `PYTHON_SOURCE_DIR`: top level directory of python source where to
-#   find `setup.py`, defaults to `.'
+#   find `pyproject.toml` or `setup.py`, defaults to `.'
 #
-# - `PYTHON_OPTS`: additional options to pass to the python command
-#   line
+# - `PYTHON_BUILD_OPTS`: additional options to pass to the
+#   `pyproject-build` command line
 #
 # - `PYTHON_IMAGE`: name of the python docker image to use
 #
+# SEE ALSO
+# ========
+#
+# - https://pypi.org/project/build/
+#
 .python:build:sdist:
-  stage: build
-  extends: .python:base
+  extends: .python:build
   variables:
     PYTHON_DIST_FILES: dist/*.tar.gz
-  artifacts:
-    paths:
-      - ${PYTHON_SOURCE_DIR}/${PYTHON_DIST_FILES}
   script:
-    - echo -e "\e[0Ksection_start:`date +%s`:python-build-sdist\r\e[0KBuild source distribution from '${PYTHON_SOURCE_DIR}'"
-    - cd ${PYTHON_SOURCE_DIR}
-    - python setup.py sdist ${PYTHON_OPTS}
+    - echo -e "\e[0Ksection_start:`date +%s`:python-build-sdist-deps[collapsed=true]\r\e[0KInstall 'build' module"
+    - pip install build
+    - echo -e "\e[0Ksection_end:`date +%s`:python-build-sdist-deps\r\e[0K"
+    - echo -e "\e[0Ksection_start:`date +%s`:python-build-sdist\r\e[0KBuild distribution 'sdist` from '${PYTHON_SOURCE_DIR}'"
+    - pyproject-build --sdist ${PYTHON_BUILD_OPTS} "${PYTHON_SOURCE_DIR}"
     - echo -e "\e[0Ksection_end:`date +%s`:python-build-sdist\r\e[0K"
 
 
@@ -118,7 +191,7 @@
 # .python:build:wheel
 # ===================
 #
-# Build the python wheel package
+# Build the python source `.tar.gz` with the `build` module
 #
 # USAGE
 # =====
@@ -131,7 +204,7 @@
 # stages:
 #   - build
 #
-# python:build:wheel {extends: '.python:build:wheel'}
+# python:build:source {extends: '.python:build:wheel'}
 #
 # REQUIREMENTS
 # ============
@@ -139,9 +212,9 @@
 # - a `build` stage must be present in your pipeline or it must be
 #   overriden by the extending job to feet your need
 #
-# - the `.on-release-tag` rules templates
+# - the `.rules-map` rules templates
 #
-# - a `setup.py` file
+# - a `pyproject.toml` or `setup.py` file
 #
 # OPTIONAL VARIABLES
 # ==================
@@ -149,21 +222,28 @@
 # - `PYTHON_DIST_FILES`: files to upload, defaults to `dist/*.whl'
 #
 # - `PYTHON_SOURCE_DIR`: top level directory of python source where to
-#   find `setup.py`, defaults to `.'
+#   find `pyproject.toml` or `setup.py`, defaults to `.'
 #
-# - `PYTHON_OPTS`: additional options to pass to the python command
-#   line
+# - `PYTHON_BUILD_OPTS`: additional options to pass to the
+#   `pyproject-build` command line
 #
 # - `PYTHON_IMAGE`: name of the python docker image to use
 #
+# SEE ALSO
+# ========
+#
+# - https://pypi.org/project/build/
+#
 .python:build:wheel:
-  extends: .python:build:sdist
+  extends: .python:build
   variables:
     PYTHON_DIST_FILES: dist/*.whl
   script:
-    - echo -e "\e[0Ksection_start:`date +%s`:python-build-wheel\r\e[0KBuild wheel distribution from '${PYTHON_SOURCE_DIR}'"
-    - cd ${PYTHON_SOURCE_DIR}
-    - python setup.py bdist_wheel ${PYTHON_OPTS}
+    - echo -e "\e[0Ksection_start:`date +%s`:python-build-wheel-deps[collapsed=true]\r\e[0KInstall 'build' module"
+    - pip install build
+    - echo -e "\e[0Ksection_end:`date +%s`:python-build-wheel-deps\r\e[0K"
+    - echo -e "\e[0Ksection_start:`date +%s`:python-build-wheel\r\e[0KBuild distribution 'wheel` from '${PYTHON_SOURCE_DIR}'"
+    - pyproject-build --wheel ${PYTHON_BUILD_OPTS} "${PYTHON_SOURCE_DIR}"
     - echo -e "\e[0Ksection_end:`date +%s`:python-build-wheel\r\e[0K"
 
 
@@ -209,7 +289,9 @@
 #
 .python:upload:
   stage: release
-  extends: .python:base
+  extends:
+    - .python:base
+    - .on-release-tag
   variables:
     PYTHON_REPOSITORY_URL: ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/pypi
   script:
@@ -229,13 +311,20 @@
 # ============
 #
 # Base template for build and upload
+# Run on all branches, release and prerelease tags
 #
 .python:base:
-  extends: .on-release-tag
+  rules:
+    - !reference [.rules-map, not-on-schedule]
+    - !reference [.rules-map, not-on-draft]
+    - !reference [.rules-map, on-release-tag]
+    - !reference [.rules-map, on-testing-tag]
+    - !reference [.rules-map, on-dev-tag]
+    - !reference [.rules-map, not-on-semantic-release-commit]
+    - !reference [.rules-map, on-branch]
   image: "${PYTHON_IMAGE}"
   variables:
     PYTHON_IMAGE: "hub.eole.education/proxyhub/library/python:latest"
-    PYTHON_OPTS: ''
     PYTHON_SOURCE_DIR: '.'
     PYTHON_DIST_FILES: 'dist/*'
 ...
-- 
GitLab