update #9
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 | |
# Builds ultralytics/ultralytics:latest images on DockerHub https://hub.docker.com/r/ultralytics | |
name: Publish Docker Images | |
on: | |
push: | |
branches: [main] | |
paths-ignore: | |
- "docs/**" | |
- "mkdocs.yml" | |
workflow_dispatch: | |
inputs: | |
Dockerfile: | |
type: boolean | |
description: Use Dockerfile | |
default: true | |
Dockerfile-cpu: | |
type: boolean | |
description: Use Dockerfile-cpu | |
Dockerfile-arm64: | |
type: boolean | |
description: Use Dockerfile-arm64 | |
Dockerfile-jetson: | |
type: boolean | |
description: Use Dockerfile-jetson | |
Dockerfile-python: | |
type: boolean | |
description: Use Dockerfile-python | |
Dockerfile-conda: | |
type: boolean | |
description: Use Dockerfile-conda | |
push: | |
type: boolean | |
description: Push images to Docker Hub | |
default: true | |
jobs: | |
docker: | |
if: github.repository == 'ultralytics/ultralytics' | |
name: Push | |
runs-on: ubuntu-latest | |
strategy: | |
fail-fast: false | |
max-parallel: 6 | |
matrix: | |
include: | |
- dockerfile: "Dockerfile" | |
tags: "latest" | |
platforms: "linux/amd64" | |
- dockerfile: "Dockerfile-cpu" | |
tags: "latest-cpu" | |
platforms: "linux/amd64" | |
- dockerfile: "Dockerfile-arm64" | |
tags: "latest-arm64" | |
platforms: "linux/arm64" | |
- dockerfile: "Dockerfile-jetson" | |
tags: "latest-jetson" | |
platforms: "linux/arm64" | |
- dockerfile: "Dockerfile-python" | |
tags: "latest-python" | |
platforms: "linux/amd64" | |
# - dockerfile: "Dockerfile-conda" | |
# tags: "latest-conda" | |
# platforms: "linux/amd64" | |
steps: | |
- name: Checkout repo | |
uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 # copy full .git directory to access full git history in Docker images | |
- name: Set up QEMU | |
uses: docker/setup-qemu-action@v3 | |
- name: Set up Docker Buildx | |
uses: docker/setup-buildx-action@v3 | |
- name: Login to Docker Hub | |
uses: docker/login-action@v3 | |
with: | |
username: ${{ secrets.DOCKERHUB_USERNAME }} | |
password: ${{ secrets.DOCKERHUB_TOKEN }} | |
- name: Retrieve Ultralytics version | |
id: get_version | |
run: | | |
VERSION=$(grep "^__version__ =" ultralytics/__init__.py | awk -F'"' '{print $2}') | |
echo "Retrieved Ultralytics version: $VERSION" | |
echo "version=$VERSION" >> $GITHUB_OUTPUT | |
VERSION_TAG=$(echo "${{ matrix.tags }}" | sed "s/latest/${VERSION}/") | |
echo "Intended version tag: $VERSION_TAG" | |
echo "version_tag=$VERSION_TAG" >> $GITHUB_OUTPUT | |
- name: Check if version tag exists on DockerHub | |
id: check_tag | |
run: | | |
RESPONSE=$(curl -s https://hub.docker.com/v2/repositories/ultralytics/ultralytics/tags/$VERSION_TAG) | |
MESSAGE=$(echo $RESPONSE | jq -r '.message') | |
if [[ "$MESSAGE" == "null" ]]; then | |
echo "Tag $VERSION_TAG already exists on DockerHub." | |
echo "exists=true" >> $GITHUB_OUTPUT | |
elif [[ "$MESSAGE" == *"404"* ]]; then | |
echo "Tag $VERSION_TAG does not exist on DockerHub." | |
echo "exists=false" >> $GITHUB_OUTPUT | |
else | |
echo "Unexpected response from DockerHub. Please check manually." | |
echo "exists=false" >> $GITHUB_OUTPUT | |
fi | |
env: | |
VERSION_TAG: ${{ steps.get_version.outputs.version_tag }} | |
- name: Build Image | |
if: github.event_name == 'push' || github.event.inputs[matrix.dockerfile] == 'true' | |
uses: nick-invision/retry@v3 | |
with: | |
timeout_minutes: 60 | |
retry_wait_seconds: 30 | |
max_attempts: 2 # retry once | |
command: | | |
docker build \ | |
--platform ${{ matrix.platforms }} \ | |
-f docker/${{ matrix.dockerfile }} \ | |
-t ultralytics/ultralytics:${{ matrix.tags }} \ | |
-t ultralytics/ultralytics:${{ steps.get_version.outputs.version_tag }} \ | |
. | |
- name: Run Tests | |
if: (github.event_name == 'push' || github.event.inputs[matrix.dockerfile] == 'true') && matrix.platforms == 'linux/amd64' && matrix.dockerfile != 'Dockerfile-conda' # arm64 images not supported on GitHub CI runners | |
run: docker run ultralytics/ultralytics:${{ matrix.tags }} /bin/bash -c "pip install pytest && pytest tests" | |
- name: Run Benchmarks | |
# WARNING: Dockerfile (GPU) error on TF.js export 'module 'numpy' has no attribute 'object'. | |
if: (github.event_name == 'push' || github.event.inputs[matrix.dockerfile] == 'true') && matrix.platforms == 'linux/amd64' && matrix.dockerfile != 'Dockerfile' && matrix.dockerfile != 'Dockerfile-conda' # arm64 images not supported on GitHub CI runners | |
run: docker run ultralytics/ultralytics:${{ matrix.tags }} yolo benchmark model=yolov8n.pt imgsz=160 verbose=0.318 | |
- name: Push Docker Image with Ultralytics version tag | |
if: (github.event_name == 'push' || (github.event.inputs[matrix.dockerfile] == 'true' && github.event.inputs.push == 'true')) && steps.check_tag.outputs.exists == 'false' && matrix.dockerfile != 'Dockerfile-conda' | |
run: | | |
docker push ultralytics/ultralytics:${{ steps.get_version.outputs.version_tag }} | |
- name: Push Docker Image with latest tag | |
if: github.event_name == 'push' || (github.event.inputs[matrix.dockerfile] == 'true' && github.event.inputs.push == 'true') | |
run: | | |
docker push ultralytics/ultralytics:${{ matrix.tags }} | |
if [[ "${{ matrix.tags }}" == "latest" ]]; then | |
t=ultralytics/ultralytics:latest-runner | |
docker build -f docker/Dockerfile-runner -t $t . | |
docker push $t | |
fi | |
- name: Notify on failure | |
if: github.event_name == 'push' && failure() # do not notify on cancelled() as cancelling is performed by hand | |
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 }} |