Merge pull request #35 from comfygit-ai/dev #10
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: Publish Packages | |
| on: | |
| workflow_dispatch: | |
| push: | |
| branches: [main] | |
| paths: | |
| - "packages/core/pyproject.toml" | |
| - "packages/cli/pyproject.toml" | |
| - "packages/deploy/pyproject.toml" | |
| permissions: | |
| contents: write | |
| id-token: write | |
| jobs: | |
| check-versions: | |
| name: Validate & Check PyPI | |
| runs-on: ubuntu-latest | |
| outputs: | |
| version: ${{ steps.extract.outputs.version }} | |
| should_publish: ${{ steps.check_pypi.outputs.should_publish }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Extract and validate versions | |
| id: extract | |
| run: | | |
| CORE_VERSION=$(grep -m1 '^version' packages/core/pyproject.toml | sed 's/.*"\([^"]*\)".*/\1/') | |
| CLI_VERSION=$(grep -m1 '^version' packages/cli/pyproject.toml | sed 's/.*"\([^"]*\)".*/\1/') | |
| DEPLOY_VERSION=$(grep -m1 '^version' packages/deploy/pyproject.toml | sed 's/.*"\([^"]*\)".*/\1/') | |
| echo "Core version: $CORE_VERSION" | |
| echo "CLI version: $CLI_VERSION" | |
| echo "Deploy version: $DEPLOY_VERSION" | |
| if [ "$CORE_VERSION" != "$CLI_VERSION" ] || [ "$CORE_VERSION" != "$DEPLOY_VERSION" ]; then | |
| echo "::error::Version mismatch! core=$CORE_VERSION cli=$CLI_VERSION deploy=$DEPLOY_VERSION" | |
| echo "Lockstep versioning requires all packages to have the same version." | |
| echo "Run: make bump-version VERSION=X.Y.Z" | |
| exit 1 | |
| fi | |
| echo "version=$CORE_VERSION" >> $GITHUB_OUTPUT | |
| echo "✓ All versions match: $CORE_VERSION" | |
| - name: Check if version exists on PyPI | |
| id: check_pypi | |
| run: | | |
| VERSION="${{ steps.extract.outputs.version }}" | |
| # Check if comfygit-core version exists on PyPI | |
| HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" "https://pypi.org/pypi/comfygit-core/$VERSION/json") | |
| if [ "$HTTP_STATUS" = "200" ]; then | |
| echo "Version $VERSION already exists on PyPI, skipping publish" | |
| echo "should_publish=false" >> $GITHUB_OUTPUT | |
| else | |
| echo "Version $VERSION not found on PyPI, will publish" | |
| echo "should_publish=true" >> $GITHUB_OUTPUT | |
| fi | |
| publish-core: | |
| name: Publish Core to PyPI | |
| needs: check-versions | |
| if: needs.check-versions.outputs.should_publish == 'true' | |
| runs-on: ubuntu-latest | |
| environment: pypi | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v5 | |
| - name: Build comfygit-core | |
| run: uv build --package comfygit-core --no-sources | |
| - name: Publish to PyPI | |
| run: uv publish --trusted-publishing automatic | |
| wait-for-pypi: | |
| name: Wait for PyPI Availability | |
| needs: [check-versions, publish-core] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Wait for comfygit-core on PyPI | |
| run: | | |
| VERSION="${{ needs.check-versions.outputs.version }}" | |
| MAX_ATTEMPTS=20 | |
| SLEEP_SECONDS=15 | |
| echo "Waiting for comfygit-core $VERSION to be available on PyPI..." | |
| for i in $(seq 1 $MAX_ATTEMPTS); do | |
| HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" "https://pypi.org/pypi/comfygit-core/$VERSION/json") | |
| if [ "$HTTP_STATUS" = "200" ]; then | |
| echo "✓ comfygit-core $VERSION is now available on PyPI" | |
| exit 0 | |
| fi | |
| echo "Attempt $i/$MAX_ATTEMPTS: Not yet available (HTTP $HTTP_STATUS), waiting ${SLEEP_SECONDS}s..." | |
| sleep $SLEEP_SECONDS | |
| done | |
| echo "::error::Timeout waiting for comfygit-core $VERSION on PyPI after $((MAX_ATTEMPTS * SLEEP_SECONDS))s" | |
| exit 1 | |
| publish-cli: | |
| name: Publish CLI to PyPI | |
| needs: [check-versions, wait-for-pypi] | |
| runs-on: ubuntu-latest | |
| environment: pypi | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v5 | |
| - name: Build comfygit (CLI) | |
| run: uv build --package comfygit --no-sources | |
| - name: Publish to PyPI | |
| run: uv publish --trusted-publishing automatic | |
| wait-for-cli: | |
| name: Wait for CLI Availability | |
| needs: [check-versions, publish-cli] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Wait for comfygit on PyPI | |
| run: | | |
| VERSION="${{ needs.check-versions.outputs.version }}" | |
| MAX_ATTEMPTS=20 | |
| SLEEP_SECONDS=15 | |
| echo "Waiting for comfygit $VERSION to be available on PyPI..." | |
| for i in $(seq 1 $MAX_ATTEMPTS); do | |
| HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" "https://pypi.org/pypi/comfygit/$VERSION/json") | |
| if [ "$HTTP_STATUS" = "200" ]; then | |
| echo "✓ comfygit $VERSION is now available on PyPI" | |
| exit 0 | |
| fi | |
| echo "Attempt $i/$MAX_ATTEMPTS: Not yet available (HTTP $HTTP_STATUS), waiting ${SLEEP_SECONDS}s..." | |
| sleep $SLEEP_SECONDS | |
| done | |
| echo "::error::Timeout waiting for comfygit $VERSION on PyPI after $((MAX_ATTEMPTS * SLEEP_SECONDS))s" | |
| exit 1 | |
| publish-deploy: | |
| name: Publish Deploy to PyPI | |
| needs: [check-versions, wait-for-cli] | |
| runs-on: ubuntu-latest | |
| environment: pypi | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v5 | |
| - name: Build comfygit-deploy | |
| run: uv build --package comfygit-deploy --no-sources | |
| - name: Publish to PyPI | |
| run: uv publish --trusted-publishing automatic | |
| create-release: | |
| name: Create GitHub Release | |
| needs: [check-versions, publish-core, publish-cli, publish-deploy] | |
| if: always() && needs.publish-core.result == 'success' && needs.publish-cli.result == 'success' && needs.publish-deploy.result == 'success' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Generate changelog | |
| id: changelog | |
| env: | |
| ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} | |
| run: | | |
| VERSION="v${{ needs.check-versions.outputs.version }}" | |
| # Find the previous tag | |
| PREV_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "") | |
| if [ -z "$PREV_TAG" ]; then | |
| echo "No previous tag found, generating changelog from recent commits" | |
| COMMITS=$(git log --pretty=format:"- %s (%h)" --no-merges | head -50) | |
| else | |
| echo "Generating changelog since $PREV_TAG" | |
| COMMITS=$(git log ${PREV_TAG}..HEAD --pretty=format:"- %s (%h)" --no-merges) | |
| fi | |
| # Generate AI summary if API key is available | |
| AI_SUMMARY="" | |
| if [ -n "$ANTHROPIC_API_KEY" ]; then | |
| echo "Generating AI summary with Claude Haiku..." | |
| # Build the prompt | |
| PROMPT="You are writing release notes for ComfyGit, a git-based environment manager for ComfyUI. This release includes comfygit-core (the library), comfygit (the CLI), and comfygit-deploy (remote deployment CLI). Given these git commits, write a brief 2-3 sentence summary of the key changes in this release. Be concise and focus on user-facing improvements. Do not use bullet points, just prose. Commits: | |
| $COMMITS" | |
| # Build JSON payload using jq to handle escaping properly | |
| JSON_PAYLOAD=$(jq -n \ | |
| --arg prompt "$PROMPT" \ | |
| '{ | |
| model: "claude-haiku-4-5-20251001", | |
| max_tokens: 300, | |
| messages: [{role: "user", content: $prompt}] | |
| }') | |
| # Call Anthropic API | |
| RESPONSE=$(curl -s https://api.anthropic.com/v1/messages \ | |
| -H "Content-Type: application/json" \ | |
| -H "x-api-key: $ANTHROPIC_API_KEY" \ | |
| -H "anthropic-version: 2023-06-01" \ | |
| -d "$JSON_PAYLOAD" 2>/dev/null) | |
| # Extract the summary from response | |
| AI_SUMMARY=$(echo "$RESPONSE" | jq -r '.content[0].text // empty' 2>/dev/null) | |
| if [ -n "$AI_SUMMARY" ]; then | |
| echo "AI summary generated successfully" | |
| else | |
| echo "Failed to generate AI summary, continuing without it" | |
| fi | |
| else | |
| echo "No ANTHROPIC_API_KEY found, skipping AI summary" | |
| fi | |
| # Build changelog body | |
| { | |
| echo "## Packages" | |
| echo "" | |
| echo "- \`comfygit-core==${{ needs.check-versions.outputs.version }}\`" | |
| echo "- \`comfygit==${{ needs.check-versions.outputs.version }}\`" | |
| echo "- \`comfygit-deploy==${{ needs.check-versions.outputs.version }}\`" | |
| echo "" | |
| if [ -n "$AI_SUMMARY" ]; then | |
| echo "## Summary" | |
| echo "" | |
| echo "$AI_SUMMARY" | |
| echo "" | |
| fi | |
| echo "## What's Changed" | |
| echo "" | |
| echo "$COMMITS" | |
| echo "" | |
| echo "**Full Changelog**: https://github.com/${{ github.repository }}/compare/${PREV_TAG:-initial}...${VERSION}" | |
| } > changelog.md | |
| cat changelog.md | |
| - name: Create Release | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| VERSION="v${{ needs.check-versions.outputs.version }}" | |
| # Check if release already exists | |
| if gh release view "$VERSION" &>/dev/null; then | |
| echo "Release $VERSION already exists, skipping" | |
| exit 0 | |
| fi | |
| gh release create "$VERSION" \ | |
| --title "Release $VERSION" \ | |
| --notes-file changelog.md \ | |
| --latest |