Update publish.yml #75
This file contains 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
# Ultralytics YOLO 🚀, AGPL-3.0 license | |
# Publish pip package to PyPI https://pypi.org/project/ultralytics/ and Docs to https://docs.ultralytics.com | |
name: Publish to PyPI and Deploy Docs | |
on: | |
push: | |
branches: [main] | |
workflow_dispatch: | |
inputs: | |
pypi: | |
type: boolean | |
description: Publish to PyPI | |
docs: | |
type: boolean | |
description: Deploy Docs | |
jobs: | |
publish: | |
if: github.repository == 'IvorZhu331/ultralytics' | |
name: Publish | |
runs-on: ubuntu-latest | |
steps: | |
- name: Checkout code | |
uses: actions/checkout@v4 | |
with: | |
fetch-depth: "0" # pulls all commits (needed correct last updated dates in Docs) | |
- name: Set up Python environment | |
uses: actions/setup-python@v5 | |
with: | |
python-version: "3.11" | |
cache: "pip" # caching pip dependencies | |
- name: Install dependencies | |
run: | | |
python -m pip install --upgrade pip wheel build twine | |
pip install -e ".[dev]" --extra-index-url https://download.pytorch.org/whl/cpu | |
- name: Check PyPI version | |
shell: python | |
run: | | |
import os | |
import ultralytics | |
from ultralytics.utils.checks import check_latest_pypi_version | |
v_local = tuple(map(int, ultralytics.__version__.split('.'))) | |
v_pypi = tuple(map(int, check_latest_pypi_version().split('.'))) | |
print(f'Local version is {v_local}') | |
print(f'PyPI version is {v_pypi}') | |
d = [a - b for a, b in zip(v_local, v_pypi)] # diff | |
increment_patch = (d[0] == d[1] == 0) and (0 < d[2] < 3) # publish if patch version increments by 1 or 2 | |
increment_minor = (d[0] == 0) and (d[1] == 1) and v_local[2] == 0 # publish if minor version increments | |
increment = increment_patch or increment_minor | |
os.system(f'echo "increment={increment}" >> $GITHUB_OUTPUT') | |
os.system(f'echo "version={ultralytics.__version__}" >> $GITHUB_OUTPUT') | |
if increment: | |
print('Local version is higher than PyPI version. Publishing new version to PyPI ✅.') | |
id: check_pypi | |
- name: Publish to PyPI | |
continue-on-error: true | |
if: (github.event_name == 'push' || github.event.inputs.pypi == 'true') && steps.check_pypi.outputs.increment == 'True' | |
env: | |
PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }} | |
run: | | |
python -m build | |
python -m twine upload dist/* -u __token__ -p $PYPI_TOKEN | |
- name: Deploy Docs | |
continue-on-error: true | |
if: (github.event_name == 'push' || github.event.inputs.docs == 'true') && github.repository == 'ultralytics/ultralytics' && github.actor == 'glenn-jocher' | |
env: | |
PERSONAL_ACCESS_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }} | |
INDEXNOW_KEY: ${{ secrets.INDEXNOW_KEY_DOCS }} | |
run: | | |
export JUPYTER_PLATFORM_DIRS=1 | |
python docs/build_docs.py | |
git config --global user.name "Glenn Jocher" | |
git config --global user.email "[email protected]" | |
git clone https://github.com/ultralytics/docs.git docs-repo | |
cd docs-repo | |
git checkout gh-pages || git checkout -b gh-pages | |
rm -rf * | |
cp -R ../site/* . | |
echo "$INDEXNOW_KEY" > "$INDEXNOW_KEY.txt" | |
git add . | |
LATEST_HASH=$(git rev-parse --short=7 HEAD) | |
git commit -m "Update Docs for 'ultralytics ${{ steps.check_pypi.outputs.version }} - $LATEST_HASH'" | |
git push https://[email protected]/ultralytics/docs.git gh-pages | |
- name: Generate and Publish Release Notes | |
env: | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
LATEST_VERSION: ${{ steps.check_pypi.outputs.version }} | |
AZURE_API_KEY: ${{ secrets.AZURE_API_KEY }} | |
AZURE_OPENAI_ENDPOINT: ${{ secrets.AZURE_OPENAI_ENDPOINT }} | |
shell: python | |
run: | | |
import requests | |
import os | |
import json | |
# Define variables | |
repo = 'IvorZhu331/ultralytics' | |
latest_version = os.getenv('LATEST_VERSION') | |
token = os.getenv('GITHUB_TOKEN') | |
azure_openai_api_key = os.getenv('AZURE_API_KEY') | |
azure_openai_endpoint = os.getenv('AZURE_OPENAI_ENDPOINT') | |
# GitHub API endpoints | |
commits_url = f'https://api.github.com/repos/{repo}/commits' | |
releases_url = f'https://api.github.com/repos/{repo}/releases' | |
headers = {'Authorization': f'token {token}'} | |
# Function to get the latest commit diff | |
def get_latest_commit_diff(): | |
response = requests.get(commits_url, headers=headers) | |
if response.status_code == 200: | |
commits = response.json() | |
if commits: | |
latest_commit_sha = commits[0]['sha'] | |
diff_url = f'https://api.github.com/repos/{repo}/commits/{latest_commit_sha}' | |
diff_response = requests.get(diff_url, headers=headers) | |
if diff_response.status_code == 200: | |
diff_data = diff_response.json() | |
return diff_data.get('files', []) | |
else: | |
print(f"Failed to get commit diff: {diff_response.content}") | |
else: | |
print("No commits found.") | |
else: | |
print(f"Failed to get commits: {response.content}") | |
return [] | |
# Function to summarize the commit diff using Azure OpenAI API | |
def summarize_diff(diff_files): | |
if not diff_files: | |
return "No changes detected." | |
diff_texts = [file.get('patch', '') for file in diff_files] | |
combined_diff = "\n".join(diff_texts) | |
summary_prompt = { | |
"prompt": f"Summarize the following commit diff:\n\n{combined_diff}", | |
"max_tokens": 100 | |
} | |
headers = { | |
'Content-Type': 'application/json', | |
'api-key': azure_openai_api_key | |
} | |
response = requests.post(azure_openai_endpoint, headers=headers, data=json.dumps(summary_prompt)) | |
if response.status_code == 200: | |
summary = response.json().get('choices', [{}])[0].get('text', '').strip() | |
return summary | |
else: | |
print(f"Failed to summarize diff: {response.content}") | |
return "Summary generation failed." | |
# Function to get release by tag name | |
def get_release_by_tag(tag_name): | |
response = requests.get(releases_url, headers=headers) | |
if response.status_code == 200: | |
releases = response.json() | |
for release in releases: | |
if release['tag_name'] == tag_name: | |
return release | |
else: | |
print(f"Failed to get releases: {response.content}") | |
return None | |
# Fetch the latest commit diff | |
diff_files = get_latest_commit_diff() | |
# Generate summary of the diff | |
diff_summary = summarize_diff(diff_files) | |
print(f"Diff Summary: {diff_summary}") | |
# Generate release notes with summary | |
release_notes = f"## What's New in {latest_version}\n\n{diff_summary}" | |
# Check if a release with the same tag already exists | |
existing_release = get_release_by_tag(latest_version) | |
if existing_release: | |
# Update the existing release | |
update_url = f'{releases_url}/{existing_release["id"]}' | |
update_payload = { | |
'tag_name': latest_version, | |
'name': f'Release {latest_version}', | |
'body': existing_release['body'] + '\n\n' + release_notes, | |
'draft': False, | |
'prerelease': False | |
} | |
response = requests.patch(update_url, headers=headers, data=json.dumps(update_payload)) | |
if response.status_code == 200: | |
print(f'Successfully updated release {latest_version}') | |
else: | |
print(f'Failed to update release {latest_version}: {response.content}') | |
else: | |
# Create a new release | |
release_payload = { | |
'tag_name': latest_version, | |
'name': f'Release {latest_version}', | |
'body': release_notes, | |
'draft': False, | |
'prerelease': False | |
} | |
response = requests.post(releases_url, headers=headers, data=json.dumps(release_payload)) | |
if response.status_code == 201: | |
print(f'Successfully created release {latest_version}') | |
else: | |
print(f'Failed to create release {latest_version}: {response.content}') | |
- name: Notify on Slack (Success) | |
if: success() && github.event_name == 'push' && steps.check_pypi.outputs.increment == 'True' | |
uses: slackapi/[email protected] | |
with: | |
payload: | | |
{"text": "<!channel> GitHub Actions success for ${{ github.workflow }} ✅\n\n\n*Repository:* https://github.com/${{ github.repository }}\n*Action:* https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}\n*Author:* ${{ github.actor }}\n*Event:* NEW 'ultralytics ${{ steps.check_pypi.outputs.version }}' pip package published 😃\n*Job Status:* ${{ job.status }}\n*Pull Request:* <https://github.com/${{ github.repository }}/pull/${{ env.PR_NUMBER }}> ${{ env.PR_TITLE }}\n"} | |
env: | |
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL_YOLO }} | |
- name: Notify on Slack (Failure) | |
if: failure() | |
uses: slackapi/[email protected] | |
with: | |
payload: | | |
{"text": "<!channel> GitHub Actions error for ${{ github.workflow }} ❌\n\n\n*Repository:* https://github.com/${{ github.repository }}\n*Action:* https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}\n*Author:* ${{ github.actor }}\n*Event:* ${{ github.event_name }}\n*Job Status:* ${{ job.status }}\n*Pull Request:* <https://github.com/${{ github.repository }}/pull/${{ env.PR_NUMBER }}> ${{ env.PR_TITLE }}\n"} | |
env: | |
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL_YOLO }} |