GitLab CI 如何升级 Python 包版本

5
我想知道是否可以在GitLab CI Runner中提高存储在GitLab中的Python软件包版本。
我有一个示例程序包结构:
/package
  /src
    /__init__.py
     main.py
  setup.py
  Dockerfile
  .gitlab-ci.yml

init.py 包含如下内容:

  __version__ = '1.0.0'

setup.py 包括:

  setup(
        name='foo',
        version=src.__version__,
        packages=find_packages(),
        install_required=[foo, bar]
  )

这里展示了发布和更新Python包的简单工作流程:在GitHub和PyPI上发布新版本Python包的最佳工作流程和实践。但是,我们是否可以在直接通过gitlab-ci发布时自动更新__init__.py中的版本号?

gitlab-ci允许您使用任何docker镜像,因此不要直接在gitlab-ci的基础镜像上执行python,而是使用一个基于python的镜像,并使用您想要的任何版本来运行您的代码。 - Daksh M.
2个回答

7

我喜欢使用bump2version软件包来实现这个功能。

这是我的gitlab-ci.yml文件,几乎只有最基本的设置:

image: python:latest

# Change pip's cache directory to be inside the project directory since we can
# only cache local items.
variables:
  PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"

# Pip's cache doesn't store the python packages
# https://pip.pypa.io/en/stable/reference/pip_install/#caching
#
# If you want to also cache the installed packages, you have to install
# them in a virtualenv and cache it as well.
cache:
  paths:
    - .cache/pip
    - venv/

before_script:
  - python --version
  - pip install virtualenv
  - virtualenv venv
  - source venv/bin/activate
  - pip install -r requirements.txt

stages:
  - build
  - release

upload package:
  stage: release
  script:
    - pip install twine bump2version
    - bump2version --tag release
    - python setup.py sdist bdist_wheel
    - TWINE_PASSWORD=${PYPI_TOKEN} TWINE_USERNAME=__token__ python -m twine upload --repository-url https://upload.pypi.org/legacy/ dist/*
    # Necessary to avoid a bug corrupting the version in setup.py. Just in case it's forgotten to do manually. Now we only have to explicitly bump version for major or minors.
    - bump2version patch
    - git config --global user.email "${GITLAB_USER_EMAIL}"
    - git config --global user.name "${GITLAB_USER_NAME}"
    - git remote set-url origin "https://gitlab-ci-token:${MY_PUSH_TOKEN}@gitlab.com/${CI_PROJECT_NAMESPACE}/${CI_PROJECT_NAME}.git"
    - git push -o ci.skip --tags origin HEAD:${CI_COMMIT_REF_NAME}
  artifacts:
    paths:
      - dist/*.whl
  only:
    - master

我的项目根目录下还有一个 .bumpversion.cfg 文件,内容如下:

[bumpversion]
commit = True
tag = False
current_version = 0.1.0-dev0
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(\-(?P<release>[a-z]+)(?P<build>\d+))?
serialize = 
    {major}.{minor}.{patch}-{release}{build}
    {major}.{minor}.{patch}

[bumpversion:file:setup.py]

[bumpversion:part:build]

[bumpversion:part:release]
optional_value = gamma
values = 
    dev
    gamma

两个自定义变量被使用。它们需要添加到仓库设置中的CI变量中。如果您想要在非受保护的分支上使用它们,请确保取消选中受保护的检查。

  • MY_PUSH_TOKEN - 这是我在我的个人资料中创建的个人访问令牌。它具有“read_repository”和“write_repository”权限。我是此仓库的所有者/维护者,因此授予了在此仓库上推送的权限。

  • PYPI_TOKEN - 可选,需要将软件包推送到 pypi.org。

最后值得一提的是:

  • 以上示例使用一个在组内的仓库,如果您有一个不在组内的单独的仓库,则可能需要更改set-url origin地址。

  • -o ci.skip 参数可以防止构建管道触发循环。

用法:

  • 创建特性分支
  • 推送代码
  • 创建合并请求
  • 将 MR 合并到主分支

CI作业负责打包、发布、上传和升级到下一个补丁版本。

要升级到主版本或次要版本,请在特性分支中从本地命令行手动调用它并进行推送。

bump2version 工具还会自动处理标签。

我使用了一些资源来解决此问题:


1
一个选项是使用setuptools_scm(来自Python Packaging Authority)。为了确定版本,setuptools_scm查看三个方面:
  • 最新标签(带有版本号)
  • 到该标签的距离(例如,自最新标签以来的修订次数)
  • 工作目录状态(例如,自最新标签以来未提交的更改)
如果您有一种自动标记发布的机制,则以上方法效果最佳,但您也可以选择手动添加标记。无论如何,您想要的是setuptools_scm选择最新的标记(例如2.1.12)并将其用于更新库的版本。
下面的示例说明了典型设置的外观。我使用了semantic-delivery-gitlab(基于提交消息使用语义化版本控制)来标记各个提交,但其他方式也可以。 master分支被视为发布分支。
配置setuptools_scm:
# pyproject.toml
[build-system]
requires = ["setuptools>=45", "wheel", "setuptools_scm>=6.2"]

[tool.setuptools_scm]
write_to = "my_library/__version__.py"


获取版本:
# `my_library/__init__.py`
try:
    from my_library.__version__ import version as __version__
except ImportError:
    pass

最小的.gitlab-ci.yaml文件:

# .gitlab-ci.yaml
stages:
  - build
  - release
  - publish

build:
  stage: build
  script:
    - pip install --upgrade pip
    - pip install setuptools setuptools_scm[toml] --upgrade
    - python setup.py bdist_wheel
  artifacts:
    expire_in: 7 days
    paths:
      - dist/*

.publish:
  stage: publish
  script:
    - WHEEL=$(ls dist)
    - publish_artifact.sh # Upload wheel to repository manager (e.g. artifactory)
 
publish-snapshot:
  <<: *publish
  except:
    - tags
    - master

publish-release:
  <<: *publish
  only:
    - tags

release:
  stage: release
  script:
    - npx @hutson/semantic-delivery-gitlab --token ${GITLAB_AUTH_TOKEN}
  only:
    - master
  when: manual # Manually trigger the tagging job for better control

您可能还希望将my_library/__version__.py添加到.gitignore中。在此过程结束时,您可以安装该软件包并确认其具有正确的版本:

>>> import my_library
>>> my_library.__version__
1.0.1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接