首页  >  文章  >  后端开发  >  使用 GitHub Actions 和 Commitizen 自动发布 Python 库

使用 GitHub Actions 和 Commitizen 自动发布 Python 库

WBOY
WBOY原创
2024-08-28 18:31:19894浏览

Automating Python Library Releases Using GitHub Actions and Commitizen

介绍

维护 Python 库可能具有挑战性,尤其是在发布新版本时。如果手动完成,该过程可能非常耗时且容易出错。在这篇文章中,我将引导您使用 GitHub Actions 和 Commitizen 自动化发布过程。这种方法可确保您的版本一致、遵守语义版本控制 (semver) 并保持变更日志最新,同时减少手动干预。

什么是语义版本控制?

语义版本控制 (semver) 是一种版本控制方案,它使用 MAJOR.MINOR.PATCH 格式的三个数字。该方案提供了一种清晰且可预测的方式来传达每个版本中的更改:

  • 主要:重大更改 - 任何不向后兼容的内容。
  • 次要:新功能,但向后兼容。
  • 补丁:错误修复——完全向后兼容。

语义版本控制至关重要,因为它可以帮助开发人员有效地管理依赖项。当您知道库的新版本不会引入重大更改(例如,次要更新或补丁更新)时,您可以自信地更新您的依赖项,而不必担心应用程序崩溃。

有关 semver 的更多详细信息,您可以查看 semver.org。

承诺简介

Commitizen 是一个标准化提交消息并自动执行版本控制和变更日志创建的工具。通过强制执行特定的提交消息格式,Commitizen 可以确定所需的版本升级类型(主要、次要或补丁)并自动生成变更日志。

提交消息格式遵循以下结构:

<commit-type>(<topic>): the commit message
  • 提交类型:
    • feat:表示新功能。这可能会导致次要版本冲突。如果提交包含重大更改注释,则会导致主要版本更新。
    • 修复:表示错误修复并导致补丁版本更新。
    • choreci 等:这些不会触发版本冲突。

例如:

feat(parser): add support for parsing new file formats
fix(api): handle null values in the response
feat(api): change response of me endpoint

BREAKING CHANGE: 

changes the API signature of the parser function

在此示例中,壮举提交中的重大更改注释将触发主要版本更新。这种一致性可确保您的版本号传达正确的更改级别,这对于依赖您的库的用户至关重要。

配置 Commitizen

要将 Commitizen 与您的 Python 项目集成,您需要在 pyproject.toml 文件中对其进行配置。以下是您需要添加的配置:

[tool.commitizen]
name = "cz_conventional_commits"
version = "0.1.0"
tag_format = "v$version"
version_files = [
    "pyproject.toml:version",
]
update_changelog_on_bump = true

说明:

  • name:指定要使用的提交消息约定。我们使用传统的提交格式。
  • 版本:项目的当前版本。您应该从“0.1.0”或任何您的初始版本开始。
  • tag_format:定义标签的格式,v$version 是典型格式(v1.0.0、v1.1.0 等)。
  • version_files:列出跟踪版本号的文件。此设置可确保 pyproject.toml 中的版本号自动更新。
  • update_changelog_on_bump:每当发生版本更新时自动更新 CHANGELOG.md 文件。

为什么要自动化发布过程?

手动管理版本可能很乏味并且容易出错,尤其是随着项目的增长。自动化带来了几个主要好处:

  • 一致性:确保每次都以相同的方式处理版本升级和变更日志。
  • 效率:通过减少发布新版本所涉及的手动步骤来节省时间。
  • 准确性:最大限度地减少人为错误,例如忘记更新变更日志或错误地更新版本。

概述:自动发布过程

为了让您清楚地了解自动化的工作原理,这里有一个高级概述:

  1. 合并到主分支:当拉取请求(PR)合并到主分支时,工作流会检查提交消息,决定是否需要版本更新,更新变更日志,并在必要时标记发布.
  2. 关于标签创建:当推送标签(表示新版本)时,工作流程会将新版本发布到 PyPI 并使用相应的变更日志创建 GitHub 版本。

拆分工作流程:合并事件与标签事件

为了简单明了,我们将自动化分为两个工作流程:

  1. Merge to Main Workflow
  2. On Tag Creation Workflow

Workflow 1: On Merge to Main

This workflow handles the logic of detecting changes and bumping the version:

name: Merge to Main

on:
  push:
    branches:
      - "main"

concurrency:
  group: main
  cancel-in-progress: true

jobs:
  bump:
    if: "!startsWith(github.event.head_commit.message, 'bump:')"
    runs-on: ubuntu-latest
    steps:
      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.10"
      - name: Checkout Repository
        uses: actions/checkout@v4
        with:
          token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
          fetch-depth: 0
      - name: Create bump and changelog
        uses: commitizen-tools/commitizen-action@0.21.0
        with:
          github_token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
          branch: main

Explanation:

  • Trigger: This workflow is triggered when a new commit is pushed to the main branch.
  • Concurrency: The concurrency setting ensures that only one instance of the workflow runs at a time for the main branch, preventing race conditions and duplicate version bumps.
  • bump job: It checks whether the commit message starts with ‘bump:’, which indicates an automated commit from the previous release. If not, Commitizen determines the necessary version bump based on the commit messages, updates the CHANGELOG.md, and creates a new tag.

Workflow 2: On Tag Creation

This workflow is triggered when a tag is pushed, and it handles the release process:

name: On Tag Creation

on:
  push:
    tags:
      - 'v*'

concurrency:
  group: tag-release-${{ github.ref }}
  cancel-in-progress: true

jobs:
  detect-release-parameters:
    runs-on: ubuntu-latest
    outputs:
      notes: ${{ steps.generate_notes.outputs.notes }}
    steps:
      - name: Setup Python
        uses: actions/setup-python@v5
      - name: Checkout Repository
        uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - name: Get release notes
        id: generate_notes
        uses: anmarkoulis/commitizen-changelog-reader@v1.2.0
        with:
          tag_name: ${{ github.ref }}
          changelog: CHANGELOG.md

  release:
    runs-on: ubuntu-20.04
    needs: detect-release-parameters
    steps:
      - name: Checkout repo
        uses: actions/checkout@v4
      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.10"
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install poetry
      - name: Configure pypi token
        run: |
          poetry config pypi-token.pypi ${{ secrets.PYPI_TOKEN }}
      - name: Build and publish package
        run: |
          poetry publish --build

  release-github:
    runs-on: ubuntu-latest
    needs: [release, detect-release-parameters]
    steps:
      - name: Checkout Repository
        uses: actions/checkout@v4
      - name: Create Release Notes File
        run: |
          echo "${{ join(fromJson(needs.detect-release-parameters.outputs.notes).notes, '') }}" > release_notes.txt
      - name: Create GitHub Release
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          VERSION: ${{ github.ref_name }}
        run: |
          gh release create ${{ github.ref }} \
          --title "Release $VERSION" \
          --notes-file "release_notes.txt"

Explanation:

  • Trigger: This workflow is triggered by a tag push (e.g., v1.2.0).
  • Concurrency: The concurrency setting ensures that only one instance of the workflow runs for each tag, preventing issues like multiple release attempts for the same version.
  • detect-release-parameters job: Extracts the changelog notes for the release.
  • release job: Builds the package and publishes it to PyPI using Poetry.
  • release-github job: Creates a new GitHub release with the generated release notes.

Setting Up the Personal Access Token

To ensure the workflows can perform actions like creating commits and tagging releases, you’ll need to set up a Personal Access Token (PAT) in your GitHub repository:

  1. Go to your repository on GitHub.
  2. Navigate to Settings > Secrets and variables > Actions.
  3. Click on New repository secret.
  4. Add a secret with the name PERSONAL_ACCESS_TOKEN and paste your PAT in the value field.

This token is crucial because it allows the workflow to push changes (like the updated changelog and version bump) back to the repository.

Generated CHANGELOG.md Example

After running the workflows, a CHANGELOG.md file will be generated and updated automatically. Here’s an example of what it might look like:

## v2.0.0 (2021-03-31)

### Feat

- **api**: change response of me endpoint

## v1.0.1 (2021-03-30)

### Fix

- **api**: handle null values in the response

## v1.0.0 (2021-03-30)

### Feat

- **parser**: add support for parsing new file formats

This CHANGELOG.md is automatically updated by Commitizen each time a new version is released. It categorizes changes into different sections (e.g., Feat, Fix), making it easy for users and developers to see what's new in each version.

Common Issues and Troubleshooting

Finally, here’s what a GitHub release looks like after being created by the workflow:

  • Incorrect Token Permissions: If the workflow fails due to permission errors, ensure that the PAT has the necessary scopes (e.g., repo, workflow).

  • Commitizen Parsing Issues: If Commitizen fails to parse commit messages, double-check the commit format and ensure it's consistent with the expected format.

  • Bump Commit Conflicts: If conflicts arise when the bump commit tries to merge into the main branch, you might need to manually resolve the conflicts or adjust your workflow to handle them.

  • Concurrent Executions: Without proper concurrency control, multiple commits or tags being processed simultaneously can lead to issues like duplicate version bumps or race conditions. This can result in multiple commits with the same version or incomplete releases. To avoid this, we’ve added concurrency settings to both workflows to ensure only one instance runs at a time for each branch or tag.

Conclusion and Next Steps

Automating the release process of your Python library with GitHub Actions and Commitizen not only saves time but also ensures consistency and reduces human errors. With this setup, you can focus more on developing new features and less on the repetitive tasks of managing releases.

As a next step, consider extending your CI/CD pipeline to include automated testing, code quality checks, or even security scans. This would further enhance the robustness of your release process.

Call to Action

If you found this post helpful, please feel free to share it with others who might benefit. I’d love to hear your thoughts or any questions you might have in the comments below. Have you implemented similar workflows in your projects? Share your experiences!

参考文献和进一步阅读

  • 语义版本控制官方网站
  • 提交文档
  • GitHub Actions 文档

以上是使用 GitHub Actions 和 Commitizen 自动发布 Python 库的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn