| |
| |
|
|
| 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 |
| default: true |
| Dockerfile-arm64: |
| type: boolean |
| description: Use Dockerfile-arm64 |
| default: true |
| Dockerfile-jetson-jetpack6: |
| type: boolean |
| description: Use Dockerfile-jetson-jetpack6 |
| default: true |
| Dockerfile-jetson-jetpack5: |
| type: boolean |
| description: Use Dockerfile-jetson-jetpack5 |
| default: true |
| Dockerfile-jetson-jetpack4: |
| type: boolean |
| description: Use Dockerfile-jetson-jetpack4 |
| default: true |
| Dockerfile-python: |
| type: boolean |
| description: Use Dockerfile-python |
| default: true |
| Dockerfile-conda: |
| type: boolean |
| description: Use Dockerfile-conda |
| default: true |
| push: |
| type: boolean |
| description: Publish all Images to Docker Hub |
|
|
| jobs: |
| docker: |
| if: github.repository == 'ultralytics/ultralytics' |
| name: Push |
| runs-on: ubuntu-latest |
| strategy: |
| fail-fast: false |
| max-parallel: 10 |
| 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-jetpack6" |
| tags: "latest-jetson-jetpack6" |
| platforms: "linux/arm64" |
| - dockerfile: "Dockerfile-jetson-jetpack5" |
| tags: "latest-jetson-jetpack5" |
| platforms: "linux/arm64" |
| - dockerfile: "Dockerfile-jetson-jetpack4" |
| tags: "latest-jetson-jetpack4" |
| platforms: "linux/arm64" |
| - dockerfile: "Dockerfile-python" |
| tags: "latest-python" |
| platforms: "linux/amd64" |
| |
| |
| |
| steps: |
| - name: Cleanup disk |
| |
| uses: jlumbroso/free-disk-space@v1.3.1 |
| with: |
| tool-cache: true |
|
|
| - name: Checkout repo |
| uses: actions/checkout@v4 |
| with: |
| fetch-depth: 0 |
|
|
| - 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: 120 |
| retry_wait_seconds: 60 |
| max_attempts: 2 |
| 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' |
| run: docker run ultralytics/ultralytics:${{ matrix.tags }} /bin/bash -c "pip install pytest && pytest tests" |
|
|
| - name: Run Benchmarks |
| |
| if: (github.event_name == 'push' || github.event.inputs[matrix.dockerfile] == 'true') && matrix.platforms == 'linux/amd64' && matrix.dockerfile != 'Dockerfile' && matrix.dockerfile != 'Dockerfile-conda' |
| 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() |
| uses: slackapi/slack-github-action@v1.27.0 |
| 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 }} |
|
|