首頁  >  文章  >  後端開發  >  使用 GitHub Actions 和 Commitizen 自動發布 Python 函式庫

使用 GitHub Actions 和 Commitizen 自動發布 Python 函式庫

WBOY
WBOY原創
2024-08-28 18:31:19779瀏覽

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