diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index beb9f1e14..e16aadf32 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -94,35 +94,65 @@ jobs: exit 1 fi - - name: Extract version and release notes + - name: Build Slack payload if: success() - id: release-info + id: slack env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + RELEASE_TAG: ${{ inputs.release_tag }} run: | - version=$(uv run python -c "import re; m = re.search(r'__version__\s*=\s*[\"\\x27]([^\"\\x27]+)', open('lib/crewai/src/crewai/__init__.py').read()); print(m.group(1))") - echo "version=$version" >> $GITHUB_OUTPUT + payload=$(uv run python -c " + import json, re, subprocess, sys - tag="${{ inputs.release_tag }}" - if [ -z "$tag" ]; then - tag="$version" - fi + with open('lib/crewai/src/crewai/__init__.py') as f: + m = re.search(r\"__version__\s*=\s*[\\\"']([^\\\"']+)\", f.read()) + version = m.group(1) if m else 'unknown' - # Fetch release body and convert GitHub markdown to Slack mrkdwn - notes=$(gh release view "$tag" --json body -q '.body' 2>/dev/null || echo "") - if [ -n "$notes" ]; then - notes=$(echo "$notes" \ - | sed 's/^### \(.*\)/*\1*/g' \ - | sed 's/^## \(.*\)/*\1*/g' \ - | sed 's/\*\*\([^*]*\)\*\*/*\1*/g' \ - | sed 's/^- /• /g') - fi + import os + tag = os.environ.get('RELEASE_TAG') or version - # Build JSON payload with proper escaping via jq - payload=$(jq -nc \ - --arg version "$version" \ - --arg notes "$notes" \ - '{text: ":rocket: *crewAI v\($version)* published to \n\n\($notes)"}') + try: + r = subprocess.run(['gh','release','view',tag,'--json','body','-q','.body'], + capture_output=True, text=True, check=True) + body = r.stdout.strip() + except Exception: + body = '' + + blocks = [ + {'type':'section','text':{'type':'mrkdwn', + 'text':f':rocket: \`crewai v{version}\` published to PyPI'}}, + {'type':'section','text':{'type':'mrkdwn', + 'text':f' · '}}, + {'type':'divider'}, + ] + + if body: + heading, items = '', [] + for line in body.split('\n'): + line = line.strip() + if not line: continue + hm = re.match(r'^#{2,3}\s+(.*)', line) + if hm: + if heading and items: + skip = heading in ('What\\'s Changed','') or 'Contributors' in heading + if not skip: + txt = f'*{heading}*\n' + '\n'.join(f'• {i}' for i in items) + blocks.append({'type':'section','text':{'type':'mrkdwn','text':txt}}) + heading, items = hm.group(1), [] + elif line.startswith('- '): + items.append(re.sub(r'\*\*([^*]*)\*\*', r'*\1*', line[2:])) + if heading and items: + skip = heading in ('What\\'s Changed','') or 'Contributors' in heading + if not skip: + txt = f'*{heading}*\n' + '\n'.join(f'• {i}' for i in items) + blocks.append({'type':'section','text':{'type':'mrkdwn','text':txt}}) + + blocks.append({'type':'divider'}) + blocks.append({'type':'section','text':{'type':'mrkdwn', + 'text':f'\`\`\`uv add \"crewai[tools]=={version}\"\`\`\`'}}) + + print(json.dumps({'blocks':blocks})) + ") echo "payload=$payload" >> $GITHUB_OUTPUT - name: Notify Slack @@ -131,4 +161,4 @@ jobs: with: webhook: ${{ secrets.SLACK_WEBHOOK_URL }} webhook-type: incoming-webhook - payload: ${{ steps.release-info.outputs.payload }} + payload: ${{ steps.slack.outputs.payload }}