name: Publish to PyPI & GitHub Release on: push: # Tag 推送:发布到正式 PyPI tags: - "v*.*.*" # Push 到 main 分支:发布到 TestPyPI branches: - main workflow_dispatch: inputs: tag_name: description: "Tag name to release (e.g., v1.0.0)" required: true default: "v1.0.0" permissions: contents: write id-token: write jobs: build: name: Build distribution runs-on: ubuntu-latest outputs: version: ${{ steps.version.outputs.version }} steps: - name: Checkout code uses: actions/checkout@v6 with: fetch-depth: 0 ref: main - name: Extract version from tag id: version run: | if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then VERSION="${{ github.event.inputs.tag_name }}" else VERSION="${{ github.ref_name }}" fi echo "version=${VERSION#v}" >> $GITHUB_OUTPUT echo "Tag: $VERSION" - name: Install uv run: | curl -LsSf https://astral.sh/uv/install.sh | sh echo "$HOME/.local/bin" >> $GITHUB_PATH - name: Get commit hash id: commit run: | COMMIT_HASH=$(git rev-parse HEAD) echo "hash=${COMMIT_HASH}" >> $GITHUB_OUTPUT echo "Commit hash: ${COMMIT_HASH}" - name: Build with uv run: | # TestPyPI 发布时使用 commit hash 作为包名 if [ "${{ github.event_name }}" == "push" ] && [ "${{ github.ref }}" == "refs/heads/main" ]; then sed -i "s/^name = \".*\"/name = \"${{ steps.commit.outputs.hash }}\"/" pyproject.toml fi uv sync uv build - name: Check distribution run: | uv pip install twine uv run twine check dist/* - uses: actions/upload-artifact@v4 with: name: dist path: dist/ - name: Package model files run: | mkdir -p model-package cd models/trpg-final cp model.onnx model.onnx.data config.json tokenizer.json tokenizer_config.json special_tokens_map.json vocab.txt ../../model-package/ cd ../.. cd model-package zip -r ../model.zip . cd .. ls -lh model.zip - uses: actions/upload-artifact@v4 with: name: model-zip path: model.zip publish-testpypi: name: Publish to TestPyPI needs: build runs-on: ubuntu-latest if: github.event_name == 'push' && github.ref == 'refs/heads/main' environment: name: test-pypi url: https://test.pypi.org/p/${{ github.sha }}/ steps: - name: Download dist uses: actions/download-artifact@v4 with: name: dist path: dist/ - name: Install twine run: pip install twine - name: Publish to TestPyPI env: TWINE_USERNAME: __token__ TWINE_PASSWORD: ${{ secrets.TEST_PYPI_TOKEN }} run: | twine upload --repository testpypi --skip-existing --verbose dist/* publish-pypi: name: Publish to PyPI needs: build runs-on: ubuntu-latest # Tag 推送或手动触发时发布 if: (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')) || github.event_name == 'workflow_dispatch' environment: name: pypi url: https://pypi.org/p/base-model-trpgner permissions: id-token: write steps: - name: Download dist uses: actions/download-artifact@v4 with: name: dist path: dist/ - name: Publish to PyPI uses: pypa/gh-action-pypi-publish@release/v1 create-release: name: Create GitHub Release with ONNX needs: [build, publish-pypi] runs-on: ubuntu-latest # Tag 推送或手动触发时创建 if: (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')) || github.event_name == 'workflow_dispatch' permissions: contents: write steps: - name: Checkout code uses: actions/checkout@v6 with: fetch-depth: 0 # 使用 main 分支代码生成 CHANGELOG ref: main - name: Generate CHANGELOG id: changelog uses: requarks/changelog-action@v1 with: token: ${{ github.token }} tag: ${{ github.event_name == 'workflow_dispatch' && inputs.tag_name || github.ref_name }} includeInvalidCommits: true changelogFilePath: CHANGELOG.md writeToFile: true useGitmojis: false - name: Download artifacts uses: actions/download-artifact@v4 with: pattern: "*" path: artifacts/ merge-multiple: true - name: Debug artifact structure run: | echo "📁 Artifact directory tree:" tree artifacts/ || ls -laR artifacts/ - name: Create Release env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then VERSION="${{ github.event.inputs.tag_name }}" else VERSION="${{ github.ref_name }}" fi cat > release_notes.md << 'EOF' ## 📦 安装 ### pip 安装 ```bash pip install base-model-trpgner ``` ### 使用 uv(推荐) ```bash uv pip install base-model-trpgner ``` ### 训练模式 ```bash pip install base-model-trpgner[train] ``` ## 🚀 快速开始 ```python from base_model_trpgner import TRPGParser parser = TRPGParser() result = parser.parse("风雨 2024-06-08 21:44:59 剧烈的疼痛...") print(result) ``` --- ${{ steps.changelog.outputs.changes }} EOF if gh release view "${VERSION}" --repo "${{ github.repository }}" >/dev/null 2>&1; then echo "📝 Release ${VERSION} 已存在,更新..." ASSETS=$(gh release view "${VERSION}" --repo "${{ github.repository }}" --json assets -q '.assets[].name') for asset in $ASSETS; do gh release delete-asset "${VERSION}" "$asset" --repo "${{ github.repository }}" || true done gh release edit "${VERSION}" \ --repo "${{ github.repository }}" \ --notes-file release_notes.md \ --title "🚀 ${VERSION}" gh release upload "${VERSION}" \ artifacts/* \ --repo "${{ github.repository }}" --clobber else echo "✨ 创建新 release ${VERSION}..." gh release create "${VERSION}" \ --repo "${{ github.repository }}" \ --notes-file release_notes.md \ --title "🚀 ${VERSION}" \ artifacts/* fi - name: Commit CHANGELOG.md if: hashFiles('CHANGELOG.md') != '' uses: stefanzweifel/git-auto-commit-action@v7 with: branch: main commit_message: "docs: update CHANGELOG.md for ${{ github.event_name == 'workflow_dispatch' && inputs.tag_name || github.ref_name }} [skip ci]" file_pattern: CHANGELOG.md