Skip to content

[DLS] Models update on self-hosted runners (by @yangjianfeng1208 via workflow_dispatch) #44

[DLS] Models update on self-hosted runners (by @yangjianfeng1208 via workflow_dispatch)

[DLS] Models update on self-hosted runners (by @yangjianfeng1208 via workflow_dispatch) #44

name: "[DLS] Models update on self-hosted runners"
run-name: "[DLS] Models update on self-hosted runners (by @${{ github.actor }} via ${{ github.event_name }})"
on:
schedule:
- cron: '0 5 * * MON' # 5:00 UTC each Monday
workflow_dispatch:
inputs:
models_to_download:
description: 'Which models to download?'
required: true
default: 'all'
type: choice
options:
- all
- public
- omz
- specific_model
specific_model_name:
description: 'What SPECIFIC model do you want to download?'
required: false
type: string
specific_model_path:
description: 'Where do you want to download your SPECIFIC model? (public/omz)'
required: false
type: string
runner_labels:
description: "List of runner(s) labels (example: DLS-TGL-02,DLS-ARL-01)"
required: false
type: string
runner_labels_windows:
description: "List of Windows runner(s) labels (example: DLS-ARL-10)"
required: false
type: string
permissions: {}
env:
MODELS_PATH: "$HOME/models"
MODELS_PATH_WINDOWS: 'C:\\models'
MODELS_DIR_MIN_SIZE_MB: 10
DEFAULT_LABELS: "DLS-ARL-01,DLS-ARL-02,DLS-ARL-03,DLS-TGL-01,DLS-TGL-02,DLS-TGL-03,DLS-TGL-04,DLS-TGL-05"
DEFAULT_LABELS_WINDOWS: "DLS-ARL-10"
jobs:
setup-runners:
name: Set runners to execute update
runs-on: ubuntu-latest
outputs:
linux_runners: ${{ steps.set-labels.outputs.linux_runners }}
windows_runners: ${{ steps.set-labels.outputs.windows_runners }}
steps:
- name: Set runners labels
id: set-labels
env:
RAW_LINUX_LABELS: ${{ inputs.runner_labels }}
RAW_WIN_LABELS: ${{ inputs.runner_labels_windows }}
DEF_LINUX_LABELS: ${{ env.DEFAULT_LABELS }}
DEF_WIN_LABELS: ${{ env.DEFAULT_LABELS_WINDOWS }}
run: |
LINUX_LABELS="$RAW_LINUX_LABELS"
if [ -z "$LINUX_LABELS" ]; then
LINUX_LABELS="$DEF_LINUX_LABELS"
fi
LINUX_ARRAY=$(echo "$LINUX_LABELS" | jq -Rc 'split(",")')
echo "linux_runners=$LINUX_ARRAY" >> $GITHUB_OUTPUT
WIN_LABELS="$RAW_WIN_LABELS"
if [ -z "$WIN_LABELS" ]; then
WIN_LABELS="$DEF_WIN_LABELS"
fi
WIN_ARRAY=$(echo "$WIN_LABELS" | jq -Rc 'split(",")')
echo "windows_runners=$WIN_ARRAY" >> $GITHUB_OUTPUT
# update_linux_hosts:
# name: Update on Linux runners
# needs: setup-runners
# permissions:
# contents: read
# strategy:
# fail-fast: false
# matrix:
# runner: ${{ fromJson(needs.setup-runners.outputs.linux_runners) }}
# runs-on:
# - ${{ matrix.runner }}
# steps:
# - name: Get script
# uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # 5.0.0
# with:
# persist-credentials: false
# path: dlstreamer-repo
# - name: Download only specific model
# env:
# model_path: ${{ inputs.specific_model_path }}
# model_name: ${{ inputs.specific_model_name }}
# if: ${{ inputs.models_to_download == 'specific_model' }}
# run: |
# MODEL_PATH=$model_path
# MODEL_NAME=$model_name
# export MODELS_PATH=${{ env.MODELS_PATH }}
# echo "MODEL_PATH=$MODEL_PATH"
# echo "MODEL_NAME=$MODEL_NAME"
# echo "Downloading specific model ${{ env.MODELS_PATH }}/$MODEL_PATH/$MODEL_NAME" >> $GITHUB_STEP_SUMMARY
# if [ -d "${{ env.MODELS_PATH }}/$MODEL_PATH/$MODEL_NAME" ]; then
# echo "Removing $MODEL_NAME directory"
# rm -rf "${{ env.MODELS_PATH }}/$MODEL_PATH/$MODEL_NAME"
# if [[ "$MODEL_PATH" == "public" ]]; then
# ./dlstreamer-repo/samples/download_public_models.sh "$MODEL_NAME" coco128
# elif [[ "$MODEL_PATH" == "omz" ]]; then
# mkdir -p .virtualenvs/dlstreamer
# python3 -m venv .virtualenvs/dlstreamer
# source .virtualenvs/dlstreamer/bin/activate
# pip3 install --no-cache-dir --upgrade tensorflow==2.19.1 openvino-dev[onnx]==2024.6.0 torch==2.8.0
# export MODELS_PATH=${{ env.MODELS_PATH }}
# ./dlstreamer-repo/samples/download_omz_models.sh $MODEL_NAME
# deactivate
# fi
# fi
# - name: Prepare directories - public models
# if: ${{ inputs.models_to_download == 'public' || inputs.models_to_download == 'all' || github.event_name == 'schedule' }}
# run: |
# # Prepare directories with backup of existing ones
# # 1) mv public_old public_old_old
# # 2) mv public public_old
# if [ -d "${{ env.MODELS_PATH }}/public_old" ]; then
# echo "Changing directories names: public_old -> public_old_old"
# [ -d "${{ env.MODELS_PATH }}/public_old_old" ] && rm -r "${{ env.MODELS_PATH }}/public_old_old"
# mv "${{ env.MODELS_PATH }}/public_old" "${{ env.MODELS_PATH }}/public_old_old"
# fi
# if [ -d "${{ env.MODELS_PATH }}/public" ]; then
# echo "Changing directories names: public -> public_old"
# [ -d "${{ env.MODELS_PATH }}/public_old" ] && rm -r "${{ env.MODELS_PATH }}/public_old"
# mv "${{ env.MODELS_PATH }}/public" "${{ env.MODELS_PATH }}/public_old"
# fi
# - name: Prepare directories - OMZ models
# if: ${{ inputs.models_to_download == 'omz' || inputs.models_to_download == 'all' || github.event_name == 'schedule' }}
# run: |
# # Prepare directories with backup of existing ones
# # 1) mv intel intel_old
# # 2) mv intel_old intel_old_old
# if [ -d "${{ env.MODELS_PATH }}/intel_old" ]; then
# echo "Changing directories names: intel_old -> intel_old_old"
# [ -d "${{ env.MODELS_PATH }}/intel_old_old" ] && rm -r "${{ env.MODELS_PATH }}/intel_old_old"
# mv "${{ env.MODELS_PATH }}/intel_old" "${{ env.MODELS_PATH }}/intel_old_old"
# fi
# if [ -d "${{ env.MODELS_PATH }}/intel" ]; then
# echo "Changing directories names: intel -> intel_old"
# [ -d "${{ env.MODELS_PATH }}/intel_old" ] && rm -r "${{ env.MODELS_PATH }}/intel_old"
# mv "${{ env.MODELS_PATH }}/intel" "${{ env.MODELS_PATH }}/intel_old"
# fi
# - name: Download public models
# id: download-public
# if: ${{ inputs.models_to_download == 'public' || inputs.models_to_download == 'all' || github.event_name == 'schedule' }}
# run: |
# export MODELS_PATH=${{ env.MODELS_PATH }}
# echo "Downloading public models"
# ./dlstreamer-repo/samples/download_public_models.sh all coco128
# - name: Download OMZ models (setup venv, dependencies and download)
# id: download-omz
# if: ${{ inputs.models_to_download == 'omz' || inputs.models_to_download == 'all' || github.event_name == 'schedule' }}
# run: |
# mkdir -p .virtualenvs/dlstreamer
# python3 -m venv .virtualenvs/dlstreamer
# source .virtualenvs/dlstreamer/bin/activate
# pip3 install --no-cache-dir --upgrade tensorflow==2.19.1 openvino-dev[onnx]==2024.6.0 torch==2.8.0
# export MODELS_PATH=${{ env.MODELS_PATH }}
# ./dlstreamer-repo/samples/download_omz_models.sh
# deactivate
# - name: Verify public models downloading
# id: verify-public
# if: >
# steps.download-public.outcome == 'success' &&
# (inputs.models_to_download == 'public' || inputs.models_to_download == 'all' || github.event_name == 'schedule')
# run: |
# if [ -z "$( ls -A ${{ env.MODELS_PATH }}/public )" ]; then
# echo "Public models not downloaded correctly - directory not created ❌"
# echo "Public models not downloaded - directory not created ❌" >> $GITHUB_STEP_SUMMARY
# exit 1
# else
# echo "Public models directory created"
# echo "Public models directory created" >> $GITHUB_STEP_SUMMARY
# DIR_SIZE_MB=$(du -sm "${{ env.MODELS_PATH }}/public" | cut -f1)
# echo "Public models directory size: ${DIR_SIZE_MB} MB"
# echo "Public models directory size: ${DIR_SIZE_MB} MB" >> $GITHUB_STEP_SUMMARY
# if [ "$DIR_SIZE_MB" -ge "${{ env.MODELS_DIR_MIN_SIZE_MB }}" ]; then
# echo "Public models downloaded ✅"
# echo "Public models downloaded ✅" >> $GITHUB_STEP_SUMMARY
# else
# Public models not downloaded correctly - directory too small ❌"
# Public models not downloaded correctly - directory too small ❌" >> $GITHUB_STEP_SUMMARY
# fi
# fi
# - name: Verify OMZ models downloading
# id: verify-omz
# if: >
# steps.download-omz.outcome == 'success' &&
# (inputs.models_to_download == 'omz' || inputs.models_to_download == 'all' || github.event_name == 'schedule')
# run: |
# if [ -z "$( ls -A ${{ env.MODELS_PATH }}/intel )" ]; then
# echo "Open Model Zoo models not downloaded correctly - directory not created ❌"
# echo "Open Model Zoo models not downloaded - directory not created ❌" >> $GITHUB_STEP_SUMMARY
# exit 1
# else
# echo "Open Model Zoo models directory created"
# echo "Open Model Zoo models directory created" >> $GITHUB_STEP_SUMMARY
# DIR_SIZE_MB=$(du -sm "${{ env.MODELS_PATH }}/intel" | cut -f1)
# echo "Open Model Zoo models directory size: ${DIR_SIZE_MB} MB"
# echo "Open Model Zoo models directory size: ${DIR_SIZE_MB} MB" >> $GITHUB_STEP_SUMMARY
# if [ "$DIR_SIZE_MB" -ge "${{ env.MODELS_DIR_MIN_SIZE_MB }}" ]; then
# echo "Open Model Zoo models downloaded ✅"
# echo "Open Model Zoo models downloaded ✅" >> $GITHUB_STEP_SUMMARY
# else
# Open Model Zoo models not downloaded correctly - directory too small ❌"
# Open Model Zoo models not downloaded correctly - directory too small ❌" >> $GITHUB_STEP_SUMMARY
# fi
# fi
# - name: Manage public models directories after success
# if: ${{ steps.verify-public.outcome == 'success' && steps.download-public.outcome == 'success' }}
# run: |
# [ -d "${{ env.MODELS_PATH }}/public_old_old" ] && rm -rf "${{ env.MODELS_PATH }}/public_old_old"
# echo "New public models set up ✅" >> $GITHUB_STEP_SUMMARY
# - name: Manage OMZ models directories after success
# if: ${{ steps.verify-omz.outcome == 'success' && steps.download-omz.outcome == 'success' }}
# run: |
# [ -d "${{ env.MODELS_PATH }}/intel_old_old" ] && rm -rf "${{ env.MODELS_PATH }}/intel_old_old"
# echo "New Open Model Zoo models set up ✅" >> $GITHUB_STEP_SUMMARY
# - name: Restore public models directories after fail
# if: ${{ always() && steps.download-public.outcome != 'skipped' && !(steps.verify-public.outcome == 'success' && steps.download-public.outcome == 'success') }}
# run: |
# [ -d "${{ env.MODELS_PATH }}/public" ] && rm -rf "${{ env.MODELS_PATH }}/public"
# [ -d "${{ env.MODELS_PATH }}/public_old" ] && mv "${{ env.MODELS_PATH }}/public_old" "${{ env.MODELS_PATH }}/public"
# [ -d "${{ env.MODELS_PATH }}/public_old_old" ] && mv "${{ env.MODELS_PATH }}/public_old_old" "${{ env.MODELS_PATH }}/public_old"
# echo "Old public models restored" >> $GITHUB_STEP_SUMMARY
# - name: Restore OMZ models directories after fail
# if: ${{ always() && steps.download-omz.outcome != 'skipped' && !(steps.verify-omz.outcome == 'success' && steps.download-omz.outcome == 'success') }}
# run: |
# [ -d "${{ env.MODELS_PATH }}/intel" ] && rm -rf "${{ env.MODELS_PATH }}/intel"
# [ -d "${{ env.MODELS_PATH }}/intel_old" ] && mv "${{ env.MODELS_PATH }}/intel_old" "${{ env.MODELS_PATH }}/intel"
# [ -d "${{ env.MODELS_PATH }}/intel_old_old" ] && mv "${{ env.MODELS_PATH }}/intel_old_old" "${{ env.MODELS_PATH }}/intel_old"
# echo "Old Open Model Zoo models restored" >> $GITHUB_STEP_SUMMARY
# - name: Clean up
# if: always()
# run: |
# rm -rf dlstreamer-repo .virtualenvs
# rm -rf $HOME/.virtualenvs
update_windows_hosts:
name: Update on Windows runners
# needs: [setup-runners, update_linux_hosts]
needs: [setup-runners]
permissions:
contents: read
strategy:
fail-fast: false
matrix:
runner: ${{ fromJson(needs.setup-runners.outputs.windows_runners) }}
runs-on:
- ${{ matrix.runner }}
steps:
- name: Initialize Emojis
shell: powershell
run: |
$emojis = @{
"EPASS" = [char]0x2705 # ✅
"EFAIL" = [char]0x274C # ❌
"EWARN" = [char]0x26A0 # ⚠️
}
$lines = New-Object System.Collections.Generic.List[string]
foreach ($name in $emojis.Keys) {
$lines.Add("$name=$($emojis[$name])")
}
$utf8NoBom = New-Object System.Text.UTF8Encoding $false
[System.IO.File]::AppendAllLines($env:GITHUB_ENV, $lines, $utf8NoBom)
- name: Install Rclone
shell: powershell
run: |
$installDir = "C:\rclone"
if (!(Test-Path $installDir)) { New-Item -ItemType Directory -Path $installDir -Force }
Write-Host "Downloading Rclone..."
$zipPath = Join-Path $env:TEMP "rclone.zip"
Invoke-WebRequest https://downloads.rclone.org/rclone-current-windows-amd64.zip -OutFile $zipPath
Write-Host "Extracting..."
Expand-Archive $zipPath -DestinationPath $env:TEMP -Force
$exe = Get-ChildItem -Path $env:TEMP -Filter rclone.exe -Recurse | Select-Object -First 1
Copy-Item $exe.FullName -Destination "$installDir\rclone.exe" -Force
echo "$installDir" >> $env:GITHUB_PATH
Write-Host "Rclone is ready at $installDir"
- name: Verify rclone installation
run: rclone version
- name: Prepare Temp Directory
id: prep-dir
shell: powershell
run: |
$base = Join-Path "${{ env.MODELS_PATH_WINDOWS }}" "models"
$tempBase = "${base}_temp"
if (Test-Path $tempBase) { Remove-Item -Recurse -Force $tempBase }
New-Item -ItemType Directory -Path $tempBase -Force
Write-Host "Temp directory ready at $tempBase"
- name: Sync Models via Rclone (Windows)
shell: powershell
env:
REMOTE_USER: ${{ secrets.DLS_MODEL_SYNC_SSH_USER }}
REMOTE_HOST: ${{ secrets.DLS_MODEL_SYNC_SSH_HOST }}
SSH_KEY_CONTENT: ${{ secrets.DLS_MODEL_SYNC_SSH_PRIVATE_KEY }}
run: |
$ErrorActionPreference = "Continue"
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
$keyPath = Join-Path $env:TEMP "id_rsa_rclone"
$cleanKey = ($env:SSH_KEY_CONTENT -replace "`r`n", "`n").Trim()
Set-Content -Path $keyPath -Value $cleanKey -Encoding Ascii
$folders = @("intel", "public")
$fixedKeyPath = $keyPath.Replace('\', '/')
$remotePrefix = ":sftp,host='$env:REMOTE_HOST',user='$env:REMOTE_USER',key_file='$fixedKeyPath',ask_password=false:"
$base = Join-Path "C:\models" "models_temp"
if (Get-Content $keyPath | Select-Object -First 1 | Select-String "BEGIN") {
Write-Host "[OK] Private key format looks valid."
} else {
Write-Error "[ERROR] Private key file is corrupted!"
exit 1
}
$remoteUser = $env:REMOTE_USER
$remoteBase = "/home/$remoteUser/models"
foreach ($folder in $folders) {
$remotePath = "$remoteBase/$folder"
$localPath = Join-Path $base $folder
Write-Host "`n--- Checking Remote: $remotePath ---"
$testPath = rclone lsf "$remotePrefix$remotePath" --max-depth 1 2>$null
if ($null -eq $testPath -or [string]::IsNullOrWhiteSpace($testPath)) {
Write-Host "[SKIP] Remote directory '$remotePath' not found or empty. Skipping." -ForegroundColor Yellow
continue
}
Write-Host "Syncing from $remotePath to $localPath"
rclone copy "$remotePrefix$remotePath" "$localPath" `
--multi-thread-streams 4 `
--transfers 4 `
--sftp-ask-password=false `
--verbose `
--stats-log-level NOTICE
}
if (Test-Path $keyPath) { Remove-Item $keyPath }
- name: Verify and Summarize (Windows)
id: verify_sync
shell: powershell
run: |
$summary = ""
$rawBase = "${{ env.MODELS_PATH_WINDOWS }}"
$base = Join-Path $rawBase "models_temp"
foreach ($type in "public", "intel") {
$path = Join-Path $base $type
if (Test-Path $path) {
$size = (Get-ChildItem $path -Recurse | Measure-Object -Property Length -Sum).Sum / 1MB
$formattedSize = "{0:N2}" -f $size
if ($size -ge ${{ env.MODELS_DIR_MIN_SIZE_MB }}) {
$status = "$type models directory size: $formattedSize MB $($env:EPASS) "
} else {
$status = "$type models directory too small: $formattedSize MB $($env:EFAIL)"
}
} else {
$status = "$type directory not found! $($env:EWARN)"
}
Write-Host $status
$summary += "$status`n"
}
$summary | Out-File -FilePath $env:GITHUB_STEP_SUMMARY -Append -Encoding utf8
- name: Swap models folder on Windows
if: steps.verify_sync.outcome == 'success'
shell: powershell
run: |
$rawBase = "${{ env.MODELS_PATH_WINDOWS }}"
$originbase = Join-Path $rawBase "models"
$incomebase = Join-Path $rawBase "models_temp"
if (Test-Path $originbase) {
Remove-Item -Recurse -Force $originbase -ErrorAction SilentlyContinue
}
if (Test-Path $incomebase) {
Rename-Item -Path $incomebase -NewName "models"
Write-Host "Swap completed: temp is now production."
}
else {
Write-Error "Temp models directory not found! Swap failed."
exit 1
}
- name: Display Final Model Structure
shell: powershell
run: |
$base = "${{ env.MODELS_PATH_WINDOWS }}\models"
Write-Host "--- Final Directory Structure (Top 2 Levels) ---`n"
if (Test-Path $base) {
Get-ChildItem -Path $base -Recurse -Depth 1 |
Select-Object @{Name="Mode";Expression={$_.Mode}},
@{Name="LastWriteTime";Expression={$_.LastWriteTime.ToString("yyyy-MM-dd HH:mm")}},
@{Name="Size(MB)";Expression={if($_.PSIsContainer){"--"}else{ "{0:N2}" -f ($_.Length / 1MB) }}},
@{Name="Path";Expression={$_.FullName.Replace($base, "models")}} |
Format-Table -AutoSize
} else {
Write-Warning "Directory $base does not exist. Nothing to display."
}
- name: Clean up (Windows)
if: always()
shell: powershell
run: |
$tempBase = "${{ env.MODELS_PATH_WINDOWS }}\models_temp"
if (Test-Path $tempBase) { Remove-Item -Recurse -Force $tempBase }
Write-Host "Clean up completed."