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 == 'ultralytics/ultralytics' && github.actor == 'glenn-jocher' | |
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 = (d[0] == d[1] == 0) and (0 < d[2] < 3) # only publish if patch version increments by 1 or 2 | |
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: Extract PR Details | |
run: | | |
if [ "${{ github.event_name }}" = "pull_request" ]; then | |
PR_JSON=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" https://api.github.com/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}) | |
PR_NUMBER=${{ github.event.pull_request.number }} | |
PR_TITLE=$(echo $PR_JSON | jq -r '.title') | |
else | |
COMMIT_SHA=${{ github.event.after }} | |
PR_JSON=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" "https://api.github.com/search/issues?q=repo:${{ github.repository }}+is:pr+is:merged+sha:$COMMIT_SHA") | |
PR_NUMBER=$(echo $PR_JSON | jq -r '.items[0].number') | |
PR_TITLE=$(echo $PR_JSON | jq -r '.items[0].title') | |
fi | |
echo "PR_NUMBER=$PR_NUMBER" >> $GITHUB_ENV | |
echo "PR_TITLE=$PR_TITLE" >> $GITHUB_ENV | |
- 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 }} |