Fix outdated YAML.dump usage in benchmark.py (#24146)
#1
This file contains hidden or 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 π AGPL-3.0 License - https://ultralytics.com/license | |
| # Builds ultralytics/ultralytics:latest images on DockerHub https://hub.docker.com/r/ultralytics | |
| name: Publish Docker Images | |
| permissions: | |
| contents: read | |
| on: | |
| push: | |
| branches: [main] | |
| paths-ignore: | |
| - "docs/**" | |
| - "mkdocs.yml" | |
| workflow_dispatch: | |
| inputs: | |
| Dockerfile: | |
| type: boolean | |
| description: Dockerfile (+ runner, export) | |
| default: true | |
| Dockerfile-python: | |
| type: boolean | |
| description: Dockerfile-python (+ jupyter, cpu, runner-cpu, python-export) | |
| default: true | |
| Dockerfile-arm64: | |
| type: boolean | |
| description: Dockerfile-arm64 | |
| default: true | |
| Dockerfile-nvidia-arm64: | |
| type: boolean | |
| description: Dockerfile-nvidia-arm64 | |
| default: true | |
| Dockerfile-jetson-jetpack6: | |
| type: boolean | |
| description: Dockerfile-jetson-jetpack6 | |
| default: true | |
| Dockerfile-jetson-jetpack5: | |
| type: boolean | |
| description: Dockerfile-jetson-jetpack5 | |
| default: true | |
| Dockerfile-jetson-jetpack4: | |
| type: boolean | |
| description: Dockerfile-jetson-jetpack4 | |
| default: true | |
| Dockerfile-conda: | |
| type: boolean | |
| description: Dockerfile-conda | |
| default: true | |
| push: | |
| type: boolean | |
| description: Publish to DockerHub and ghcr.io | |
| jobs: | |
| docker: | |
| if: github.repository == 'ultralytics/ultralytics' | |
| name: Build | |
| strategy: | |
| fail-fast: false | |
| max-parallel: 10 | |
| matrix: | |
| include: | |
| # Base images with their derivatives | |
| - dockerfile: "Dockerfile" | |
| tags: "latest" | |
| platforms: "linux/amd64" | |
| runs_on: "ubuntu-latest" | |
| derivatives: "Dockerfile-runner,Dockerfile-export" | |
| - dockerfile: "Dockerfile-python" | |
| tags: "latest-python" | |
| platforms: "linux/amd64" | |
| runs_on: "ubuntu-latest" | |
| derivatives: "Dockerfile-jupyter,Dockerfile-cpu,Dockerfile-runner-cpu,Dockerfile-python-export" | |
| # Standalone base images | |
| - dockerfile: "Dockerfile-arm64" | |
| tags: "latest-arm64" | |
| platforms: "linux/arm64" | |
| runs_on: "ubuntu-24.04-arm" | |
| derivatives: "" | |
| - dockerfile: "Dockerfile-nvidia-arm64" | |
| tags: "latest-nvidia-arm64" | |
| platforms: "linux/arm64" | |
| runs_on: "ubuntu-24.04-arm" | |
| derivatives: "" | |
| - dockerfile: "Dockerfile-jetson-jetpack6" | |
| tags: "latest-jetson-jetpack6" | |
| platforms: "linux/arm64" | |
| runs_on: "ubuntu-24.04-arm" | |
| derivatives: "" | |
| - dockerfile: "Dockerfile-jetson-jetpack5" | |
| tags: "latest-jetson-jetpack5" | |
| platforms: "linux/arm64" | |
| runs_on: "ubuntu-24.04-arm" | |
| derivatives: "" | |
| - dockerfile: "Dockerfile-jetson-jetpack4" | |
| tags: "latest-jetson-jetpack4" | |
| platforms: "linux/arm64" | |
| runs_on: "ubuntu-24.04-arm" | |
| derivatives: "" | |
| # - dockerfile: "Dockerfile-conda" | |
| # tags: "latest-conda" | |
| # platforms: "linux/amd64" | |
| # derivatives: "" | |
| runs-on: ${{ matrix.runs_on }} | |
| outputs: | |
| new_release: ${{ steps.check_tag.outputs.new_release }} | |
| steps: | |
| - name: Cleanup disk space | |
| uses: ultralytics/actions/cleanup-disk@main | |
| - name: Checkout repo | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 # copy full .git directory to access full git history in Docker images | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v4 | |
| - name: Login to Docker Hub | |
| uses: docker/login-action@v4 | |
| with: | |
| username: ${{ secrets.DOCKERHUB_USERNAME }} | |
| password: ${{ secrets.DOCKERHUB_TOKEN }} | |
| - name: Login to GHCR | |
| uses: docker/login-action@v4 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.repository_owner }} | |
| password: ${{ secrets._GITHUB_TOKEN }} | |
| - name: Login to NVIDIA NGC | |
| uses: docker/login-action@v4 | |
| with: | |
| registry: nvcr.io | |
| username: $oauthtoken | |
| password: ${{ secrets.NVIDIA_NGC_API_KEY }} | |
| - 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 "new_release=false" >> $GITHUB_OUTPUT | |
| elif [[ "$MESSAGE" == *"404"* ]]; then | |
| echo "Tag $VERSION_TAG does not exist on DockerHub." | |
| echo "new_release=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "Unexpected response from DockerHub. Please check manually." | |
| echo "new_release=false" >> $GITHUB_OUTPUT | |
| fi | |
| env: | |
| VERSION_TAG: ${{ steps.get_version.outputs.version_tag }} | |
| - name: Build Base Image | |
| if: github.event_name == 'push' || github.event.inputs[matrix.dockerfile] == 'true' | |
| uses: ultralytics/actions/retry@main | |
| with: | |
| timeout_minutes: 120 | |
| retry_delay_seconds: 60 | |
| retries: 2 | |
| run: | | |
| docker build \ | |
| --platform ${{ matrix.platforms }} \ | |
| --label "org.opencontainers.image.source=https://github.com/ultralytics/ultralytics" \ | |
| --label "org.opencontainers.image.description=Ultralytics image" \ | |
| --label "org.opencontainers.image.licenses=AGPL-3.0-or-later" \ | |
| -f docker/${{ matrix.dockerfile }} \ | |
| -t ultralytics/ultralytics:${{ matrix.tags }} \ | |
| -t ultralytics/ultralytics:${{ steps.get_version.outputs.version_tag }} \ | |
| -t ghcr.io/ultralytics/ultralytics:${{ matrix.tags }} \ | |
| -t ghcr.io/ultralytics/ultralytics:${{ steps.get_version.outputs.version_tag }} \ | |
| . | |
| - name: Build Derivative Images | |
| if: (github.event_name == 'push' || github.event.inputs[matrix.dockerfile] == 'true') && matrix.derivatives != '' | |
| uses: ultralytics/actions/retry@main | |
| with: | |
| timeout_minutes: 120 | |
| retry_delay_seconds: 60 | |
| retries: 2 | |
| run: | | |
| # Build each derivative image using local base image | |
| derivatives='${{ matrix.derivatives }}' | |
| if [[ -n "$derivatives" ]]; then | |
| IFS=',' read -ra derivative_array <<< "$derivatives" | |
| for derivative in "${derivative_array[@]}"; do | |
| # Determine derivative tags | |
| derivative_tag=$(echo "$derivative" | sed 's/Dockerfile-/latest-/') | |
| derivative_version_tag=$(echo "$derivative_tag" | sed "s/latest/${{ steps.get_version.outputs.version }}/") | |
| echo "Building $derivative -> $derivative_tag" | |
| docker build \ | |
| --platform ${{ matrix.platforms }} \ | |
| --label "org.opencontainers.image.source=https://github.com/ultralytics/ultralytics" \ | |
| --label "org.opencontainers.image.description=Ultralytics $derivative image" \ | |
| --label "org.opencontainers.image.licenses=AGPL-3.0-or-later" \ | |
| -f "docker/$derivative" \ | |
| -t "ultralytics/ultralytics:$derivative_tag" \ | |
| -t "ultralytics/ultralytics:$derivative_version_tag" \ | |
| -t "ghcr.io/ultralytics/ultralytics:$derivative_tag" \ | |
| -t "ghcr.io/ultralytics/ultralytics:$derivative_version_tag" \ | |
| . | |
| done | |
| fi | |
| - name: Check Environment | |
| if: (github.event_name == 'push' || github.event.inputs[matrix.dockerfile] == 'true') && (matrix.platforms == 'linux/amd64' || matrix.platforms == 'linux/arm64') && matrix.dockerfile != 'Dockerfile-conda' | |
| run: docker run ultralytics/ultralytics:${{ (matrix.tags == 'latest-python' && 'latest-python-export') || (matrix.tags == 'latest' && 'latest-export') || matrix.tags }} /bin/bash -c "yolo checks && uv pip list" | |
| - name: Run Tests | |
| if: (github.event_name == 'push' || github.event.inputs[matrix.dockerfile] == 'true') && (matrix.platforms == 'linux/amd64' || matrix.platforms == 'linux/arm64') && matrix.dockerfile != 'Dockerfile-conda' | |
| run: docker run ultralytics/ultralytics:${{ (matrix.tags == 'latest-python' && 'latest-python-export') || (matrix.tags == 'latest' && 'latest-export') || matrix.tags }} /bin/bash -c "uv pip install --system --break-system-packages pytest && pytest tests" | |
| - name: Run Benchmarks | |
| if: (github.event_name == 'push' || github.event.inputs[matrix.dockerfile] == 'true') && (matrix.platforms == 'linux/amd64' || matrix.dockerfile == 'Dockerfile-arm64') && matrix.dockerfile != 'Dockerfile' && matrix.dockerfile != 'Dockerfile-conda' | |
| run: docker run ultralytics/ultralytics:${{ (matrix.tags == 'latest-python' && 'latest-python-export') || (matrix.tags == 'latest' && 'latest-export') || matrix.tags }} yolo benchmark model=yolo26n.pt imgsz=160 verbose=0.218 | |
| - name: Push All Images | |
| if: github.event_name == 'push' || (github.event.inputs[matrix.dockerfile] == 'true' && github.event.inputs.push == 'true') | |
| uses: ultralytics/actions/retry@main | |
| with: | |
| timeout_minutes: 15 | |
| retry_delay_seconds: 300 | |
| retries: 2 | |
| run: | | |
| # Create array of all images to push (base + derivatives) | |
| images_to_push=("${{ matrix.tags }}") | |
| # Add derivative images to array | |
| derivatives='${{ matrix.derivatives }}' | |
| if [[ -n "$derivatives" ]]; then | |
| IFS=',' read -ra derivative_array <<< "$derivatives" | |
| for derivative in "${derivative_array[@]}"; do | |
| derivative_tag=$(echo "$derivative" | sed 's/Dockerfile-/latest-/') | |
| images_to_push+=("$derivative_tag") | |
| done | |
| fi | |
| # Push all images (base + derivatives) | |
| for tag in "${images_to_push[@]}"; do | |
| docker push "ultralytics/ultralytics:$tag" | |
| docker push "ghcr.io/ultralytics/ultralytics:$tag" | |
| # Push version tag if new release | |
| if [[ "${{ steps.check_tag.outputs.new_release }}" == "true" && "${{ matrix.dockerfile }}" != "Dockerfile-conda" ]]; then | |
| version_tag=$(echo "$tag" | sed "s/latest/${{ steps.get_version.outputs.version }}/") | |
| docker push "ultralytics/ultralytics:$version_tag" | |
| docker push "ghcr.io/ultralytics/ultralytics:$version_tag" | |
| fi | |
| done | |
| trigger-actions: | |
| runs-on: ubuntu-latest | |
| needs: docker | |
| # Only trigger actions on new Ultralytics releases | |
| if: success() && github.repository == 'ultralytics/ultralytics' && github.event_name == 'push' && needs.docker.outputs.new_release == 'true' | |
| steps: | |
| - name: Trigger Additional GitHub Actions | |
| env: | |
| GH_TOKEN: ${{ secrets._GITHUB_TOKEN }} | |
| run: | | |
| sleep 60 | |
| gh workflow run deploy_cloud_run.yml \ | |
| --repo ultralytics/assistant \ | |
| --ref main | |
| notify: | |
| runs-on: ubuntu-latest | |
| needs: [docker, trigger-actions] | |
| if: always() | |
| steps: | |
| - name: Check for failure and notify | |
| if: needs.docker.result == 'failure' && github.repository == 'ultralytics/ultralytics' && github.event_name == 'push' && github.run_attempt == '1' | |
| uses: slackapi/slack-github-action@v3.0.1 | |
| with: | |
| webhook-type: incoming-webhook | |
| webhook: ${{ secrets.SLACK_WEBHOOK_URL_YOLO }} | |
| 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" |