Ultralytics CI #47
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 | |
# YOLO Continuous Integration (CI) GitHub Actions tests | |
name: Ultralytics CI | |
on: | |
push: | |
branches: [main] | |
pull_request: | |
branches: [main] | |
schedule: | |
- cron: '0 0 * * *' # runs at 00:00 UTC every day | |
workflow_dispatch: | |
inputs: | |
hub: | |
description: 'Run HUB' | |
default: false | |
type: boolean | |
benchmarks: | |
description: 'Run Benchmarks' | |
default: false | |
type: boolean | |
tests: | |
description: 'Run Tests' | |
default: false | |
type: boolean | |
gpu: | |
description: 'Run GPU' | |
default: false | |
type: boolean | |
conda: | |
description: 'Run Conda' | |
default: false | |
type: boolean | |
jobs: | |
HUB: | |
if: github.repository == 'ultralytics/ultralytics' && (github.event_name == 'schedule' || github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && github.event.inputs.hub == 'true')) | |
runs-on: ${{ matrix.os }} | |
strategy: | |
fail-fast: false | |
matrix: | |
os: [ubuntu-latest] | |
python-version: ['3.11'] | |
steps: | |
- uses: actions/checkout@v4 | |
- uses: actions/setup-python@v4 | |
with: | |
python-version: ${{ matrix.python-version }} | |
cache: 'pip' # caching pip dependencies | |
- name: Install requirements | |
shell: bash # for Windows compatibility | |
run: | | |
python -m pip install --upgrade pip wheel | |
pip install -e . --extra-index-url https://download.pytorch.org/whl/cpu | |
- name: Check environment | |
run: | | |
yolo checks | |
echo "RUNNER_OS is ${{ runner.os }}" | |
echo "GITHUB_EVENT_NAME is ${{ github.event_name }}" | |
echo "GITHUB_WORKFLOW is ${{ github.workflow }}" | |
echo "GITHUB_ACTOR is ${{ github.actor }}" | |
echo "GITHUB_REPOSITORY is ${{ github.repository }}" | |
echo "GITHUB_REPOSITORY_OWNER is ${{ github.repository_owner }}" | |
python --version | |
pip --version | |
pip list | |
- name: Test HUB training | |
shell: python | |
env: | |
API_KEY: ${{ secrets.ULTRALYTICS_HUB_API_KEY }} | |
MODEL_ID: ${{ secrets.ULTRALYTICS_HUB_MODEL_ID }} | |
run: | | |
import os | |
from ultralytics import YOLO, hub | |
api_key, model_id = os.environ['API_KEY'], os.environ['MODEL_ID'] | |
hub.login(api_key) | |
hub.reset_model(model_id) | |
model = YOLO('https://hub.ultralytics.com/models/' + model_id) | |
model.train() | |
- name: Test HUB inference API | |
shell: python | |
env: | |
API_KEY: ${{ secrets.ULTRALYTICS_HUB_API_KEY }} | |
MODEL_ID: ${{ secrets.ULTRALYTICS_HUB_MODEL_ID }} | |
run: | | |
import os | |
import requests | |
import json | |
api_key, model_id = os.environ['API_KEY'], os.environ['MODEL_ID'] | |
url = f"https://api.ultralytics.com/v1/predict/{model_id}" | |
headers = {"x-api-key": api_key} | |
data = {"size": 320, "confidence": 0.25, "iou": 0.45} | |
with open("ultralytics/assets/zidane.jpg", "rb") as f: | |
response = requests.post(url, headers=headers, data=data, files={"image": f}) | |
assert response.status_code == 200, f'Status code {response.status_code}, Reason {response.reason}' | |
print(json.dumps(response.json(), indent=2)) | |
Benchmarks: | |
if: github.event_name != 'workflow_dispatch' || github.event.inputs.benchmarks == 'true' | |
runs-on: ${{ matrix.os }} | |
strategy: | |
fail-fast: false | |
matrix: | |
os: [ubuntu-latest] | |
python-version: ['3.10'] | |
model: [yolov8n] | |
steps: | |
- uses: actions/checkout@v4 | |
- uses: actions/setup-python@v4 | |
with: | |
python-version: ${{ matrix.python-version }} | |
cache: 'pip' # caching pip dependencies | |
- name: Install requirements | |
shell: bash # for Windows compatibility | |
run: | | |
python -m pip install --upgrade pip wheel | |
pip install -e ".[export]" coverage --extra-index-url https://download.pytorch.org/whl/cpu | |
# Fix SavedModel issue "partially initialized module 'jax' has no attribute 'version' (most likely due to a circular import)" in https://github.com/google/jax/discussions/14036 | |
# pip install -U 'jax!=0.4.15' 'jaxlib!=0.4.15' | |
# yolo settings tensorboard=False | |
yolo export format=tflite imgsz=32 || true | |
- name: Check environment | |
run: | | |
yolo checks | |
echo "RUNNER_OS is ${{ runner.os }}" | |
echo "GITHUB_EVENT_NAME is ${{ github.event_name }}" | |
echo "GITHUB_WORKFLOW is ${{ github.workflow }}" | |
echo "GITHUB_ACTOR is ${{ github.actor }}" | |
echo "GITHUB_REPOSITORY is ${{ github.repository }}" | |
echo "GITHUB_REPOSITORY_OWNER is ${{ github.repository_owner }}" | |
python --version | |
pip --version | |
pip list | |
# - name: Benchmark DetectionModel | |
# shell: bash | |
# run: coverage run -a --source=ultralytics -m ultralytics.cfg.__init__ benchmark model='path with spaces/${{ matrix.model }}.pt' imgsz=160 verbose=0.318 | |
- name: Benchmark SegmentationModel | |
shell: bash | |
run: coverage run -a --source=ultralytics -m ultralytics.cfg.__init__ benchmark model='path with spaces/${{ matrix.model }}-seg.pt' imgsz=160 verbose=0.286 | |
- name: Benchmark ClassificationModel | |
shell: bash | |
run: coverage run -a --source=ultralytics -m ultralytics.cfg.__init__ benchmark model='path with spaces/${{ matrix.model }}-cls.pt' imgsz=160 verbose=0.166 | |
- name: Benchmark PoseModel | |
shell: bash | |
run: coverage run -a --source=ultralytics -m ultralytics.cfg.__init__ benchmark model='path with spaces/${{ matrix.model }}-pose.pt' imgsz=160 verbose=0.185 | |
- name: Merge Coverage Reports | |
run: | | |
coverage xml -o coverage-benchmarks.xml | |
- name: Upload Coverage Reports to CodeCov | |
if: github.repository == 'ultralytics/ultralytics' | |
uses: codecov/codecov-action@v3 | |
with: | |
flags: Benchmarks | |
env: | |
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} | |
- name: Benchmark Summary | |
run: | | |
cat benchmarks.log | |
echo "$(cat benchmarks.log)" >> $GITHUB_STEP_SUMMARY | |
Tests: | |
if: github.event_name != 'workflow_dispatch' || github.event.inputs.tests == 'true' | |
timeout-minutes: 60 | |
runs-on: ${{ matrix.os }} | |
strategy: | |
fail-fast: false | |
matrix: | |
os: [ubuntu-latest] | |
python-version: ['3.11'] | |
torch: [latest] | |
include: | |
- os: ubuntu-latest | |
python-version: '3.8' # torch 1.8.0 requires python >=3.6, <=3.8 | |
torch: '1.8.0' # min torch version CI https://pypi.org/project/torchvision/ | |
steps: | |
- uses: actions/checkout@v4 | |
- uses: actions/setup-python@v4 | |
with: | |
python-version: ${{ matrix.python-version }} | |
cache: 'pip' # caching pip dependencies | |
- name: Install requirements | |
shell: bash # for Windows compatibility | |
run: | # CoreML must be installed before export due to protobuf error from AutoInstall | |
python -m pip install --upgrade pip wheel | |
if [ "${{ matrix.torch }}" == "1.8.0" ]; then | |
pip install -e . torch==1.8.0 torchvision==0.9.0 pytest-cov "coremltools>=7.0" --extra-index-url https://download.pytorch.org/whl/cpu | |
else | |
pip install -e . pytest-cov "coremltools>=7.0" --extra-index-url https://download.pytorch.org/whl/cpu | |
fi | |
- name: Check environment | |
run: | | |
yolo checks | |
echo "RUNNER_OS is ${{ runner.os }}" | |
echo "GITHUB_EVENT_NAME is ${{ github.event_name }}" | |
echo "GITHUB_WORKFLOW is ${{ github.workflow }}" | |
echo "GITHUB_ACTOR is ${{ github.actor }}" | |
echo "GITHUB_REPOSITORY is ${{ github.repository }}" | |
echo "GITHUB_REPOSITORY_OWNER is ${{ github.repository_owner }}" | |
python --version | |
pip --version | |
pip list | |
- name: Pytest tests | |
shell: bash # for Windows compatibility | |
run: pytest --cov=ultralytics/ --cov-report xml tests/ | |
- name: Upload Coverage Reports to CodeCov | |
if: github.repository == 'ultralytics/ultralytics' # && matrix.os == 'ubuntu-latest' && matrix.python-version == '3.11' | |
uses: codecov/codecov-action@v3 | |
with: | |
flags: Tests | |
env: | |
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} | |
GPU: | |
if: github.repository == 'ultralytics/ultralytics' && (github.event_name != 'workflow_dispatch' || github.event.inputs.gpu == 'true') | |
timeout-minutes: 60 | |
runs-on: gpu-latest | |
steps: | |
- uses: actions/checkout@v4 | |
- name: Install requirements | |
run: pip install -e . | |
- name: Check environment | |
run: | | |
yolo checks | |
echo "RUNNER_OS is ${{ runner.os }}" | |
echo "GITHUB_EVENT_NAME is ${{ github.event_name }}" | |
echo "GITHUB_WORKFLOW is ${{ github.workflow }}" | |
echo "GITHUB_ACTOR is ${{ github.actor }}" | |
echo "GITHUB_REPOSITORY is ${{ github.repository }}" | |
echo "GITHUB_REPOSITORY_OWNER is ${{ github.repository_owner }}" | |
python --version | |
pip --version | |
pip list | |
- name: Pytest tests | |
run: pytest --cov=ultralytics/ --cov-report xml tests/test_cuda.py | |
- name: Upload Coverage Reports to CodeCov | |
uses: codecov/codecov-action@v3 | |
with: | |
flags: GPU | |
env: | |
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} | |
Conda: | |
if: github.repository == 'ultralytics/ultralytics' && (github.event_name == 'schedule' || github.event.inputs.conda == 'true') | |
runs-on: ${{ matrix.os }} | |
strategy: | |
fail-fast: false | |
matrix: | |
os: [ubuntu-latest] | |
python-version: ['3.11'] | |
defaults: | |
run: | |
shell: bash -el {0} | |
steps: | |
- uses: conda-incubator/setup-miniconda@v2 | |
with: | |
python-version: ${{ matrix.python-version }} | |
mamba-version: "*" | |
channels: conda-forge,defaults | |
channel-priority: true | |
activate-environment: anaconda-client-env | |
- name: Install Libmamba | |
run: | | |
conda config --set solver libmamba | |
- name: Install Ultralytics package from conda-forge | |
run: | | |
conda install -c pytorch -c conda-forge pytorch torchvision ultralytics | |
- name: Install pip packages | |
run: | | |
pip install pytest 'coremltools>=7.0' # 'openvino-dev>=2023.0' | |
- name: Check environment | |
run: | | |
echo "RUNNER_OS is ${{ runner.os }}" | |
echo "GITHUB_EVENT_NAME is ${{ github.event_name }}" | |
echo "GITHUB_WORKFLOW is ${{ github.workflow }}" | |
echo "GITHUB_ACTOR is ${{ github.actor }}" | |
echo "GITHUB_REPOSITORY is ${{ github.repository }}" | |
echo "GITHUB_REPOSITORY_OWNER is ${{ github.repository_owner }}" | |
python --version | |
conda list | |
- name: Test CLI | |
run: | | |
yolo predict model=yolov8n.pt imgsz=320 | |
yolo train model=yolov8n.pt data=coco8.yaml epochs=1 imgsz=32 | |
yolo val model=yolov8n.pt data=coco8.yaml imgsz=32 | |
yolo export model=yolov8n.pt format=torchscript imgsz=160 | |
- name: Test Python | |
run: | | |
python -c " | |
from ultralytics import YOLO | |
model = YOLO('yolov8n.pt') | |
results = model.train(data='coco8.yaml', epochs=3, imgsz=160) | |
results = model.val(imgsz=160) | |
results = model.predict(imgsz=160) | |
results = model.export(format='onnx', imgsz=160) | |
" | |
- name: PyTest | |
run: | | |
git clone https://github.com/ultralytics/ultralytics | |
pytest ultralytics/tests/test_cli.py # full tests fail due to openvino export failure | |
Summary: | |
runs-on: ubuntu-latest | |
needs: [HUB, Benchmarks, Tests, GPU, Conda] # Add job names that you want to check for failure | |
if: always() # This ensures the job runs even if previous jobs fail | |
steps: | |
- name: Check for failure and notify | |
if: (needs.HUB.result == 'failure' || needs.Benchmarks.result == 'failure' || needs.Tests.result == 'failure' || needs.GPU.result == 'failure' || needs.Conda.result == 'failure') && github.repository == 'ultralytics/ultralytics' && (github.event_name == 'schedule' || github.event_name == 'push') | |
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"} | |
env: | |
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL_YOLO }} |