diff --git a/templates/gitlab-ci-python.yml b/templates/gitlab-ci-python.yml index 25803e4412d86eb2a4f31a04c86d725e1a028d08..12acc841c1fab034327a741c07664acdb4ec7017 100644 --- a/templates/gitlab-ci-python.yml +++ b/templates/gitlab-ci-python.yml @@ -251,15 +251,7 @@ variables: case "${PYTHON_BUILD_SYSTEM:-auto}" in auto) ;; - poetry*) - log_info "--- Build system explictly declared: ${PYTHON_BUILD_SYSTEM}" - return - ;; - setuptools*) - log_info "--- Build system explictly declared: ${PYTHON_BUILD_SYSTEM}" - return - ;; - pipenv*) + poetry*|setuptools*|pipenv*) log_info "--- Build system explictly declared: ${PYTHON_BUILD_SYSTEM}" return ;; @@ -320,6 +312,14 @@ variables: fi } + function maybe_install_poetry() { + if [[ "$PYTHON_BUILD_SYSTEM" == poetry* ]] && ! command -v poetry > /dev/null + then + # shellcheck disable=SC2086 + pip install ${PIP_OPTS} "$PYTHON_BUILD_SYSTEM" + fi + } + # install requirements function install_requirements() { case "$PYTHON_BUILD_SYSTEM" in @@ -327,8 +327,7 @@ variables: if [[ ! -f "poetry.lock" ]]; then log_warn "Using Poetry but \\e[33;1mpoetry.lock\\e[0m file not found: you shall commit it with your project files" fi - # shellcheck disable=SC2086 - pip install ${PIP_OPTS} "$PYTHON_BUILD_SYSTEM" + maybe_install_poetry poetry install ${PYTHON_EXTRA_DEPS:+--extras "$PYTHON_EXTRA_DEPS"} ;; setuptools*) @@ -368,10 +367,9 @@ variables: } function _run() { - if [[ "${PYTHON_BUILD_SYSTEM}" =~ poetry.* ]] + if [[ "$PYTHON_BUILD_SYSTEM" == poetry* ]] then - # shellcheck disable=SC2086 - if ! command -v poetry > /dev/null; then pip install ${PIP_OPTS} poetry; fi + maybe_install_poetry poetry run "$@" else "$@" @@ -387,19 +385,16 @@ variables: _run pip ${PIP_OPTS} "$@" } - function _package() { - case "$PYTHON_BUILD_SYSTEM" in - poetry) - # shellcheck disable=SC2086 - if ! command -v poetry > /dev/null; then pip install ${PIP_OPTS} poetry; fi + function py_package() { + if [[ "$PYTHON_BUILD_SYSTEM" == poetry* ]] + then + maybe_install_poetry poetry build - ;; - *) + else # shellcheck disable=SC2086 pip install ${PIP_OPTS} build python -m build - ;; - esac + fi } function configure_scm_auth() { @@ -425,44 +420,7 @@ variables: fi } - function _release() { - # 0: guess packaging system - if [[ -f "pyproject.toml" ]] - then - # that might be PEP 517 if a build-backend is specified - # otherwise it might be only used as configuration file for development tools... - build_backend=$(sed -rn 's/^build-backend *= *"([^"]*)".*/\1/p' pyproject.toml) - if [[ "$build_backend" ]] - then - case "$build_backend" in - poetry.core.masonry.api) - log_info "--- Packaging system auto-detected: Poetry" - pkg_system="poetry" - ;; - setuptools.build_meta) - log_info "--- Packaging system auto-detected: Setuptools (PEP 517)" - pkg_system="setuptools" - ;; - *) - log_error "--- Unsupported PEP 517 backend \\e[33;1m${build_backend}\\e[0m: abort" - exit 1 - ;; - esac - fi - fi - - if [[ -z "$pkg_system" ]] - then - if [[ -f "setup.py" ]] - then - log_info "--- Packaging system auto-detected: Setuptools (legacy)" - pkg_system="setuptools" - else - log_error "--- Couldn't find any supported packaging system: abort" - exit 1 - fi - fi - + function py_release() { # 1: retrieve next release info from semantic-release if [ "$SEMREL_INFO_ON" ] && [ "$PYTHON_SEMREL_RELEASE_DISABLED" != "true" ] then @@ -479,19 +437,19 @@ variables: fi # 2: bumpversion (+ Git commit & tag) - if [[ "$pkg_system" == "poetry" ]] + if [[ "$PYTHON_BUILD_SYSTEM" == poetry* ]] then - # shellcheck disable=SC2086 - if ! command -v poetry > /dev/null; then pip install ${PIP_OPTS} poetry; fi + maybe_install_poetry if [[ -z "$py_next_version" ]] then py_cur_version=$(poetry version --short) py_next_version="$PYTHON_RELEASE_NEXT" fi - log_info "[Poetry] change version \\e[1;94m${py_cur_version}\\e[0m → \\e[1;94m${py_next_version}\\e[0m" + log_info "[poetry] change version \\e[1;94m${py_cur_version}\\e[0m → \\e[1;94m${py_next_version}\\e[0m" poetry version ${TRACE+--verbose} "$py_next_version" # eval exact next version py_next_version=$(poetry version --short) + # Git commit and tag git add pyproject.toml git commit -m "chore(python-release): $py_cur_version → $py_next_version" git tag "$py_next_version" @@ -503,7 +461,7 @@ variables: if [[ "$py_next_version" ]] then # explicit release version (semantic-release) - log_info "[Setuptools] bumpversion \\e[1;94m${py_cur_version}\\e[0m → \\e[1;94m${py_next_version}\\e[0m" + log_info "[bumpversion] change version \\e[1;94m${py_cur_version}\\e[0m → \\e[1;94m${py_next_version}\\e[0m" # create cfg in case it doesn't exist - will be updated by bumpversion touch .bumpversion.cfg bumpversion ${TRACE+--verbose} --current-version "$py_cur_version" --commit --message "$py_commit_message" --tag --tag-name "{new_version}" "$py_release_part" @@ -518,7 +476,7 @@ variables: # retrieve current version from setup.py py_cur_version=$(python setup.py --version) py_release_part="$PYTHON_RELEASE_NEXT" - log_info "[Setuptools] bumpversion ($py_release_part) from \\e[1;94m${py_cur_version}\\e[0m" + log_info "[bumpversion] increase \\e[1;94m${py_release_part}\\e[0m (from current \\e[1;94m${py_cur_version}\\e[0m)" bumpversion ${TRACE+--verbose} --current-version "$py_cur_version" --commit --message "$py_commit_message" --tag --tag-name "{new_version}" "$py_release_part" setup.py else log_error "--- setup.py or .bumpversion.cfg file required to retrieve current version: cannot perform release" @@ -532,67 +490,26 @@ variables: git push "$git_auth_url" --tags } - function _publish() { - # 1: guess packaging system - if [[ -f "pyproject.toml" ]] - then - # that might be PEP 517 if a build-backend is specified - # otherwise it might be only used as configuration file for development tools... - build_backend=$(sed -rn 's/^build-backend *= *"([^"]*)".*/\1/p' pyproject.toml) - if [[ "$build_backend" ]] - then - case "$build_backend" in - poetry.core.masonry.api) - log_info "--- Packaging system auto-detected: Poetry" - pkg_system="poetry" - ;; - setuptools.build_meta) - log_info "--- Packaging system auto-detected: Setuptools (PEP 517)" - pkg_system="setuptools" - ;; - *) - log_error "--- Unsupported PEP 517 backend \\e[33;1m${build_backend}\\e[0m: abort" - exit 1 - ;; - esac - fi - fi - - if [[ -z "$pkg_system" ]] + function py_publish() { + if [[ "$PYTHON_BUILD_SYSTEM" == poetry* ]] then - if [[ -f "setup.py" ]] - then - log_info "--- Packaging system auto-detected: Setuptools (legacy)" - pkg_system="setuptools" - else - log_error "--- Couldn't find any supported packaging system: abort" - exit 1 - fi - fi - - # 2: build (new version) distribution - log_info "--- build distribution packages..." - if [[ "$pkg_system" == "poetry" ]] - then - # shellcheck disable=SC2086 - if ! command -v poetry > /dev/null; then pip install ${PIP_OPTS} poetry; fi + maybe_install_poetry + + log_info "--- build packages (poetry)..." poetry build ${TRACE+--verbose} + + log_info "--- publish packages (poetry)..." + poetry config repositories.user_defined "$PYTHON_REPOSITORY_URL" + poetry publish ${TRACE+--verbose} --username "$PYTHON_REPOSITORY_USERNAME" --password "$PYTHON_REPOSITORY_PASSWORD" --repository user_defined else # shellcheck disable=SC2086 - pip install ${PIP_OPTS} build + pip install ${PIP_OPTS} build twine + + log_info "--- build packages (build)..." rm -rf dist python -m build - fi - # 3: publish built packages - log_info "--- publish distribution packages..." - if [[ "$pkg_system" == "poetry" ]] - then - poetry config repositories.user_defined "$PYTHON_REPOSITORY_URL" - poetry publish ${TRACE+--verbose} --username "$PYTHON_REPOSITORY_USERNAME" --password "$PYTHON_REPOSITORY_PASSWORD" --repository user_defined - else - # shellcheck disable=SC2086 - pip install ${PIP_OPTS} twine + log_info "--- publish packages (twine)..." twine upload ${TRACE+--verbose} --username "$PYTHON_REPOSITORY_USERNAME" --password "$PYTHON_REPOSITORY_PASSWORD" --repository-url "$PYTHON_REPOSITORY_URL" dist/* fi } @@ -601,6 +518,14 @@ variables: # ENDSCRIPT +############################################################################################### +# stages definition # +############################################################################################### +stages: + - build + - test + - publish + ############################################################################################### # Generic python job # ############################################################################################### @@ -623,14 +548,6 @@ variables: - cd ${PYTHON_PROJECT_DIR} - guess_build_system -############################################################################################### -# stages definition # -############################################################################################### -stages: - - build - - test - - publish - ############################################################################################### # build stage # ############################################################################################### @@ -639,7 +556,7 @@ py-package: extends: .python-base stage: build script: - - _package + - py_package artifacts: paths: - $PYTHON_PROJECT_DIR/dist/* @@ -840,7 +757,7 @@ py-trivy: - apt-get update - apt-get install trivy - | - if [[ "$PYTHON_BUILD_SYSTEM" =~ poetry.* ]] + if [[ "$PYTHON_BUILD_SYSTEM" == poetry* ]] then # When using Poetry, `pip freeze` outputs a requirements.txt with @file URLs for each wheel # These @file URLs in requirements.txt are not supported by Trivy @@ -891,7 +808,7 @@ py-sbom: - install_requirements - | case "$PYTHON_BUILD_SYSTEM" in - setuptools* | reqfile) + setuptools*|reqfile) _pip freeze > "${PYTHON_REQS_FILE}" ;; esac @@ -935,7 +852,7 @@ py-release: - git config --global user.name "$GITLAB_USER_LOGIN" - git checkout -B $CI_COMMIT_REF_NAME - configure_scm_auth - - _release + - py_release artifacts: paths: - $PYTHON_PROJECT_DIR/dist/* @@ -948,12 +865,12 @@ py-release: when: manual allow_failure: true -# (manual from master branch): triggers a release (tag creation) +# (auto from release tag): publishes the Python package(s) to a PyPi registry py-publish: extends: .python-base stage: publish script: - - _publish $CI_COMMIT_TAG + - py_publish $CI_COMMIT_TAG artifacts: paths: - $PYTHON_PROJECT_DIR/dist/*