fix: new ci and publish one more (#25) #4
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release to PyPI | ||
| on: | ||
| push: | ||
| tags: ["v*"] | ||
| permissions: | ||
| id-token: write # OIDC for PyPI Trusted Publishing | ||
| contents: write # allow creating GitHub releases and updating CHANGELOG | ||
| jobs: | ||
| build: | ||
| name: Build distribution | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 0 | ||
| - uses: astral-sh/setup-uv@v4 | ||
| with: | ||
| python-version: "3.12" | ||
| - name: Build package | ||
| run: uv build | ||
| - name: Upload distribution artifact | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: dist | ||
| path: dist/* | ||
| publish: | ||
| name: Publish to PyPI | ||
| needs: build | ||
| runs-on: ubuntu-latest | ||
| environment: | ||
| name: pypi | ||
| url: https://pypi.org/p/cryptoservice | ||
| permissions: | ||
| id-token: write # IMPORTANT: this permission is mandatory for trusted publishing | ||
| steps: | ||
| - name: Download distribution artifact | ||
| uses: actions/download-artifact@v4 | ||
| with: | ||
| name: dist | ||
| path: dist | ||
| - name: Publish to PyPI | ||
| uses: pypa/gh-action-pypi-publish@release/v1 | ||
| with: | ||
| skip-existing: true | ||
| verbose: true | ||
| release-notes: | ||
| name: Create GitHub Release | ||
| needs: publish | ||
| runs-on: ubuntu-latest | ||
| permissions: | ||
| contents: write # allow creating GitHub releases | ||
| env: | ||
| TAG_NAME: ${{ github.ref_name }} # e.g. v1.16.3 | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 0 | ||
| - uses: astral-sh/setup-uv@v4 | ||
| with: | ||
| python-version: "3.12" | ||
| - name: Extract version | ||
| run: | | ||
| VER="${TAG_NAME#v}" | ||
| echo "VER=$VER" >> "$GITHUB_ENV" | ||
| - name: Generate release notes from CHANGELOG | ||
| run: | | ||
| # 从 CHANGELOG.md 提取当前版本的内容 | ||
| if [ -f "CHANGELOG.md" ]; then | ||
| # 匹配版本标题格式: ## v1.16.3 (2025-01-30) 或 ## 1.16.3 | ||
| awk -v ver="$VER" ' | ||
| BEGIN { found=0 } | ||
| /^## / { | ||
| if (found) exit | ||
| if ($0 ~ ver) { found=1; next } | ||
| } | ||
| found { print } | ||
| ' CHANGELOG.md > RELEASE_BODY.md | ||
| # 如果提取失败,使用 towncrier 生成 | ||
| if [ ! -s RELEASE_BODY.md ]; then | ||
| echo "Using towncrier to generate release notes..." | ||
| uvx towncrier build --draft --version "$VER" > RELEASE_BODY.md | ||
| fi | ||
| else | ||
| # 如果没有 CHANGELOG,使用 towncrier | ||
| echo "No CHANGELOG.md found, using towncrier..." | ||
| uvx towncrier build --draft --version "$VER" > RELEASE_BODY.md | ||
| fi | ||
| echo "Release notes:" | ||
| cat RELEASE_BODY.md | ||
| - name: Create GitHub Release | ||
| uses: softprops/action-gh-release@v2 | ||
| with: | ||
| tag_name: ${{ env.TAG_NAME }} | ||
| body_path: RELEASE_BODY.md | ||
| draft: false | ||
| files: | | ||
| dist/* | ||
| - name: Notify webhook | ||
| if: secrets.WEBHOOK_URL != '' | ||
| env: | ||
| WEBHOOK_URL: ${{ secrets.WEBHOOK_URL }} | ||
| run: | | ||
| python - <<'PY' | ||
| import json, os, urllib.request | ||
| content = open("RELEASE_BODY.md", "r", encoding="utf-8").read() | ||
| tag = os.environ.get("TAG_NAME") | ||
| # 飞书通知格式 | ||
| text = f"🚀 发布 {tag} 到 PyPI\n\n{content}\n\n查看: https://pypi.org/project/cryptoservice/" | ||
| body = {"msg_type": "text", "content": {"text": text}} | ||
| webhook_url = os.environ.get("WEBHOOK_URL", "") | ||
| if webhook_url: | ||
| req = urllib.request.Request( | ||
| webhook_url, | ||
| data=json.dumps(body).encode(), | ||
| headers={"Content-Type": "application/json"} | ||
| ) | ||
| resp = urllib.request.urlopen(req) | ||
| print(f"Notification sent: {resp.status}") | ||
| else: | ||
| print("No webhook URL configured, skipping notification") | ||
| PY | ||