維護 Python 函式庫可能具有挑戰性,尤其是在發布新版本時。如果手動完成,該過程可能非常耗時且容易出錯。在這篇文章中,我將引導您使用 GitHub Actions 和 Commitizen 自動化發布流程。這種方法可確保您的版本一致、遵守語意版本控制 (semver) 並保持變更日誌最新,同時減少手動介入。
語意版本控制 (semver) 是一種版本控制方案,它使用 MAJOR.MINOR.PATCH 格式的三個數字。該方案提供了一種清晰且可預測的方式來傳達每個版本中的變更:
語意版本控制至關重要,因為它可以幫助開發人員有效地管理依賴關係。當您知道庫的新版本不會引入重大更改(例如,次要更新或補丁更新)時,您可以自信地更新您的依賴項,而不必擔心應用程式崩潰。
有關 semver 的更多詳細信息,您可以查看 semver.org。
Commitizen 是一個標準化提交訊息並自動執行版本控制和變更日誌建立的工具。透過強制執行特定的提交訊息格式,Commitizen 可以確定所需的版本升級類型(主要、次要或修補程式)並自動產生變更日誌。
提交訊息格式遵循以下結構:
<commit-type>(<topic>): the commit message
例如:
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 與您的 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
說明:
手動管理版本可能很乏味且容易出錯,尤其是隨著專案的成長。自動化帶來了幾個主要好處:
為了讓您清楚了解自動化的工作原理,這裡有一個進階概述:
為了簡單明了,我們將自動化分為兩個工作流程:
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:
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:
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:
This token is crucial because it allows the workflow to push changes (like the updated changelog and version bump) back to the repository.
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.
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.
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.
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 和 Commitizen 自動發布 Python 函式庫的詳細內容。更多資訊請關注PHP中文網其他相關文章!