mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-04-12 05:52:39 +00:00
* fix: bump litellm to >=1.83.0 to address CVE-2026-35030 Bump litellm from <=1.82.6 to >=1.83.0 to fix JWT auth bypass via OIDC cache key collision (CVE-2026-35030). Also widen devtools openai pin from ~=1.83.0 to >=1.83.0,<3 to resolve the version conflict (litellm 1.83.0 requires openai>=2.8.0). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: resolve mypy errors from litellm bump - Remove unused type: ignore[import-untyped] on instructor import - Remove all unused type: ignore[union-attr] comments (litellm types fixed) - Add hasattr guard for tool_call.function — new litellm adds ChatCompletionMessageCustomToolCall to the union which lacks .function * fix: tighten litellm pin to ~=1.83.0 (patch-only bumps) >=1.83.0,<2 is too wide — litellm has had breaking changes between minors. ~=1.83.0 means >=1.83.0,<1.84.0 — gets CVE patches but won't pull in breaking minor releases. * ci: bump uv from 0.8.4 to 0.11.3 * fix: resolve mypy errors in openai completion from 2.x type changes Use isinstance checks with concrete openai response types instead of string comparisons for proper type narrowing. Update code interpreter handling for outputs/OutputImage API changes in openai 2.x. * fix: pre-cache tiktoken encoding before VCR intercepts requests --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Alex <alex@crewai.com> Co-authored-by: Greyson LaLonde <greyson@crewai.com>
167 lines
5.2 KiB
YAML
167 lines
5.2 KiB
YAML
name: Publish to PyPI
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
inputs:
|
|
release_tag:
|
|
description: 'Release tag to publish'
|
|
required: false
|
|
type: string
|
|
|
|
jobs:
|
|
build:
|
|
name: Build packages
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
contents: read
|
|
steps:
|
|
- name: Determine release tag
|
|
id: release
|
|
run: |
|
|
if [ -n "${{ inputs.release_tag }}" ]; then
|
|
echo "tag=${{ inputs.release_tag }}" >> $GITHUB_OUTPUT
|
|
else
|
|
echo "tag=" >> $GITHUB_OUTPUT
|
|
fi
|
|
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
ref: ${{ steps.release.outputs.tag || github.ref }}
|
|
|
|
- name: Set up Python
|
|
uses: actions/setup-python@v5
|
|
with:
|
|
python-version: "3.12"
|
|
|
|
- name: Install uv
|
|
uses: astral-sh/setup-uv@v4
|
|
|
|
- name: Build packages
|
|
run: |
|
|
uv build --all-packages
|
|
rm dist/.gitignore
|
|
|
|
- name: Upload artifacts
|
|
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/crewai
|
|
permissions:
|
|
id-token: write
|
|
contents: read
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
ref: ${{ inputs.release_tag || github.ref }}
|
|
|
|
- name: Install uv
|
|
uses: astral-sh/setup-uv@v6
|
|
with:
|
|
version: "0.11.3"
|
|
python-version: "3.12"
|
|
enable-cache: false
|
|
|
|
- name: Download artifacts
|
|
uses: actions/download-artifact@v4
|
|
with:
|
|
name: dist
|
|
path: dist
|
|
|
|
- name: Publish to PyPI
|
|
env:
|
|
UV_PUBLISH_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
|
|
run: |
|
|
failed=0
|
|
for package in dist/*; do
|
|
if [[ "$package" == *"crewai_devtools"* ]]; then
|
|
echo "Skipping private package: $package"
|
|
continue
|
|
fi
|
|
echo "Publishing $package"
|
|
if ! uv publish "$package"; then
|
|
echo "Failed to publish $package"
|
|
failed=1
|
|
fi
|
|
done
|
|
if [ $failed -eq 1 ]; then
|
|
echo "Some packages failed to publish"
|
|
exit 1
|
|
fi
|
|
|
|
- name: Build Slack payload
|
|
if: success()
|
|
id: slack
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
RELEASE_TAG: ${{ inputs.release_tag }}
|
|
run: |
|
|
payload=$(uv run python -c "
|
|
import json, re, subprocess, sys
|
|
|
|
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'
|
|
|
|
import os
|
|
tag = os.environ.get('RELEASE_TAG') or version
|
|
|
|
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'<https://pypi.org/project/crewai/{version}/|View on PyPI> · <https://github.com/crewAIInc/crewAI/releases/tag/{tag}|Release notes>'}},
|
|
{'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('- ') or 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
|
|
if: success()
|
|
uses: slackapi/slack-github-action@v2.1.0
|
|
with:
|
|
webhook: ${{ secrets.SLACK_WEBHOOK_URL }}
|
|
webhook-type: incoming-webhook
|
|
payload: ${{ steps.slack.outputs.payload }}
|