AddaxAI v6.02 #38
Workflow file for this run
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
name: Build Windows release | |
on: | |
workflow_dispatch: | |
inputs: | |
info: | |
description: "Here you can manually trigger the build. ➡️ It will automatically fetch the latest release tag. ➡️ Selecting branch 'main' will upload to the official Google bucket. ➡️ Any other branch will upload to the beta-versions bucket." | |
required: false | |
default: "[dummy input field - no need to fill in]" | |
release: | |
types: | |
- published | |
jobs: | |
build-windows-release: | |
runs-on: windows-2022 | |
env: | |
# remove if proven succesful after a release triggered job | |
# RELEASE_VERSION: ${{ github.event_name == 'release' && github.event.release.tag_name || inputs.tag_name }} | |
# BUCKET_NAME: github-release-files-storage | |
CONDA_DIR: C:\Miniconda | |
BRANCH_NAME: ${{ github.event_name == 'release' && 'main' || github.ref_name }} | |
steps: | |
- name: Checkout repository | |
uses: actions/checkout@v3 | |
- name: Get latest release tag | |
id: release_info | |
uses: pozetroninc/github-action-get-latest-release@master | |
with: | |
token: ${{ secrets.GITHUB_TOKEN }} | |
repository: ${{ github.repository }} | |
- name: Set latest release tag to global | |
shell: cmd | |
run: | | |
set RELEASE_VERSION=${{ steps.release_info.outputs.release }} | |
echo RELEASE_VERSION: %RELEASE_VERSION% | |
echo RELEASE_VERSION=%RELEASE_VERSION%>> %GITHUB_ENV% | |
- name: Set bucket name based on chosen branch | |
shell: cmd | |
run: | | |
echo BRANCH_NAME is %BRANCH_NAME% | |
if "%BRANCH_NAME%"=="main" ( | |
set "BUCKET_NAME=github-release-files-storage" | |
) else ( | |
set "BUCKET_NAME=github-release-files-storage-beta-versions" | |
) | |
echo BUCKET_NAME=%BUCKET_NAME%>> %GITHUB_ENV% | |
echo BUCKET_NAME is "%BUCKET_NAME%" | |
- name: Install dependencies | |
shell: cmd | |
run: | | |
echo off | |
@setlocal EnableDelayedExpansion | |
@REM init environment vars | |
set root=%USERPROFILE%\AddaxAI | |
set conda_exe=${{ env.CONDA_DIR }}\Scripts\conda.exe | |
echo Using conda %conda_exe% | |
@REM set high timeout value and ip address for ipv4 fallback issues | |
call "%conda_exe%" config --set remote_connect_timeout_secs 120 | |
call "%conda_exe%" config --set remote_max_retries 5 | |
call "%conda_exe%" config --set remote_read_timeout_secs 120 | |
call "%conda_exe%" config --set ssl_verify False | |
call "%conda_exe%" config --set fetch_threads 2 | |
call "%conda_exe%" config --show | |
@REM refresh dir | |
if exist "%root%" ( | |
rmdir /s /q "%root%" | |
echo %root% folder removed | |
) | |
@REM set IPv4 | |
set PIP_NO_IPV6=1 | |
set CONDA_SSL_VERIFY=0 | |
set CONDA_USE_IPV4=1 | |
@REM create folder structure | |
mkdir "%root%" | |
mkdir "%root%\envs" | |
mkdir "%root%\models" | |
mkdir "%root%\models\det" | |
mkdir "%root%\models\cls" | |
mkdir "%root%\models\det\MegaDetector 5a" | |
mkdir "%root%\yolov5_versions\yolov5_old" | |
mkdir "%root%\yolov5_versions\yolov5_new" | |
echo Hello world! > "%root%\first-startup.txt" | |
@REM AddaxAI | |
git clone --ipv4 --depth 1 --branch %BRANCH_NAME% https://github.com/PetervanLunteren/EcoAssist.git "%root%\AddaxAI" | |
rmdir /s /q "%root%\AddaxAI\.git" | |
move "%root%\AddaxAI\main.py" "%root%\main.py" | |
set RAW_VERSION=${{ env.RELEASE_VERSION }} | |
set CLEAN_VERSION=%RAW_VERSION:v=% | |
echo %CLEAN_VERSION% > "%root%\AddaxAI\version.txt" | |
echo AddaxAI cloned | |
@REM MegaDetector | |
git clone --ipv4 https://github.com/agentmorris/MegaDetector.git "%root%\cameratraps" | |
pushd "%root%\cameratraps" | |
git checkout a64a8f8c467ae6c87b5ca09f54b1abe502168b50 | |
popd | |
rmdir /s /q "%root%\cameratraps\.git" | |
echo MegaDetector cloned | |
@REM YOLOv5 old | |
git clone --ipv4 https://github.com/ultralytics/yolov5.git "%root%\yolov5_versions\yolov5_old\yolov5" | |
pushd "%root%\yolov5_versions\yolov5_old\yolov5" | |
git checkout c23a441c9df7ca9b1f275e8c8719c949269160d1 | |
popd | |
rmdir /s /q "%root%\yolov5_versions\yolov5_old\yolov5\.git" | |
echo YOLOv5 old cloned | |
@REM YOLOv5 new | |
git clone --ipv4 https://github.com/ultralytics/yolov5.git "%root%\yolov5_versions\yolov5_new\yolov5" | |
pushd "%root%\yolov5_versions\yolov5_new\yolov5" | |
git checkout 3e55763d45f9c5f8217e4dad5ba1e6c1f42e3bf8 | |
popd | |
rmdir /s /q "%root%\yolov5_versions\yolov5_new\yolov5\.git" | |
echo YOLOv5 new cloned | |
@REM Human in the loop | |
git clone --ipv4 --depth 1 https://github.com/PetervanLunteren/Human-in-the-loop.git "%root%\Human-in-the-loop" | |
rmdir /s /q "%root%\Human-in-the-loop\.git" | |
echo Human-in-the-loop cloned | |
@REM Visualise detections | |
git clone --ipv4 --depth 1 https://github.com/PetervanLunteren/visualise_detection.git "%root%\visualise_detection" | |
rmdir /s /q "%root%\visualise_detection\.git" | |
echo visualise_detection cloned | |
@REM MegaDetector model 5A | |
curl --ipv4 -L https://github.com/agentmorris/MegaDetector/releases/download/v5.0/md_v5a.0.0.pt -o "%root%/models\det\MegaDetector 5a\md_v5a.0.0.pt" | |
@REM install mamba | |
call "%conda_exe%" install -n base -c conda-forge mamba -y | |
@REM DEBUG | |
set conda_exe=${{ env.CONDA_DIR }}\condabin\mamba.bat | |
@REM env-base | |
call "%conda_exe%" env create --file "%root%\cameratraps\envs\environment-detector.yml" -p "%root%\envs\env-base" | |
call "%conda_exe%" run -p "%root%\envs\env-base" pip install --timeout=120 pyqt5==5.15.2 lxml | |
call "%conda_exe%" run -p "%root%\envs\env-base" pip install --timeout=120 RangeSlider gpsphoto exifread piexif openpyxl pyarrow customtkinter CTkTable | |
call "%conda_exe%" run -p "%root%\envs\env-base" pip install --timeout=120 GitPython==3.1.30 | |
call "%conda_exe%" run -p "%root%\envs\env-base" pip install --timeout=120 folium plotly | |
call "%conda_exe%" run -p "%root%\envs\env-base" pip install --timeout=120 numpy==1.23.4 | |
call "%conda_exe%" run -p "%root%\envs\env-base" pip install --timeout=120 pytorchwildlife==1.0.2.15 | |
call "%conda_exe%" run -p "%root%\envs\env-base" pip uninstall torch torchvision -y | |
call "%conda_exe%" run -p "%root%\envs\env-base" pip install --timeout=120 torch==2.3.1+cu118 torchvision==0.18.1+cu118 --index-url https://download.pytorch.org/whl/cu118 | |
@REM env-pytorch | |
call "%conda_exe%" create -p "%root%\envs\env-pytorch" python=3.8 -y | |
call "%conda_exe%" run -p "%root%\envs\env-pytorch" "%conda_exe%" pytorch==2.3.0 torchvision==0.18.0 torchaudio==2.3.0 pytorch-cuda=11.8 -c pytorch -c nvidia -y | |
call "%conda_exe%" run -p "%root%\envs\env-pytorch" pip install --timeout=120 ultralytics==8.0.230 | |
call "%conda_exe%" run -p "%root%\envs\env-pytorch" pip install --timeout=120 timm | |
call "%conda_exe%" run -p "%root%\envs\env-pytorch" pip install --timeout=120 pandas | |
call "%conda_exe%" run -p "%root%\envs\env-pytorch" pip install --timeout=120 numpy | |
call "%conda_exe%" run -p "%root%\envs\env-pytorch" pip install --timeout=120 opencv-python | |
call "%conda_exe%" run -p "%root%\envs\env-pytorch" pip install --timeout=120 pillow | |
call "%conda_exe%" run -p "%root%\envs\env-pytorch" pip install --timeout=120 dill | |
call "%conda_exe%" run -p "%root%\envs\env-pytorch" pip install --timeout=120 hachoir | |
call "%conda_exe%" run -p "%root%\envs\env-pytorch" pip install --timeout=120 versions | |
call "%conda_exe%" run -p "%root%\envs\env-pytorch" pip install --timeout=120 jsonpickle | |
@REM env-tensorflow | |
call "%conda_exe%" create -p "%root%\envs\env-tensorflow" python=3.11 -y | |
call "%conda_exe%" run -p "%root%\envs\env-tensorflow" pip install --timeout=120 tensorflow | |
call "%conda_exe%" run -p "%root%\envs\env-tensorflow" pip install --timeout=120 huggingface_hub==0.23.0 | |
call "%conda_exe%" run -p "%root%\envs\env-tensorflow" pip install --timeout=120 jax==0.4.28 | |
call "%conda_exe%" run -p "%root%\envs\env-tensorflow" pip install --timeout=120 jaxlib==0.4.28 | |
call "%conda_exe%" run -p "%root%\envs\env-tensorflow" pip install --timeout=120 keras==3.3.3 | |
call "%conda_exe%" run -p "%root%\envs\env-tensorflow" pip install --timeout=120 keras_cv==0.9.0 | |
call "%conda_exe%" run -p "%root%\envs\env-tensorflow" pip install --timeout=120 kimm==0.2.5 | |
call "%conda_exe%" run -p "%root%\envs\env-tensorflow" pip install --timeout=120 matplotlib==3.9.0 | |
call "%conda_exe%" run -p "%root%\envs\env-tensorflow" pip install --timeout=120 numpy==1.26.4 | |
call "%conda_exe%" run -p "%root%\envs\env-tensorflow" pip install --timeout=120 pandas==2.2.2 | |
call "%conda_exe%" run -p "%root%\envs\env-tensorflow" pip install --timeout=120 pytest==8.3.0 | |
call "%conda_exe%" run -p "%root%\envs\env-tensorflow" pip install --timeout=120 pyyaml==6.0.1 | |
call "%conda_exe%" run -p "%root%\envs\env-tensorflow" pip install --timeout=120 scikit-learn==1.4.2 | |
call "%conda_exe%" run -p "%root%\envs\env-tensorflow" pip install --timeout=120 tqdm==4.66.4 | |
call "%conda_exe%" run -p "%root%\envs\env-tensorflow" pip install --timeout=120 jsonpickle==4.0.1 | |
call "%conda_exe%" run -p "%root%\envs\env-tensorflow" pip install --timeout=120 opencv-python==4.11.0.86 | |
# @REM install PyInstaller | |
# call "%conda_exe%" create -p "${{ env.CONDA_DIR }}\envs\env-fresh" python=3.8 pyinstaller -y | |
# @REM normal executable | |
# call "%conda_exe%" run -p "${{ env.CONDA_DIR }}\envs\env-fresh" pyinstaller --onefile --noconsole --icon="%root%\AddaxAI\imgs\logo_small_bg.ico" --distpath="%USERPROFILE%\dist" --workpath="%USERPROFILE%\build" "%root%\main.py" | |
# move "%USERPROFILE%\dist\main.exe" "%root%/AddaxAI %RELEASE_VERSION%.exe" | |
# @REM debug executable | |
# call "%conda_exe%" run -p "${{ env.CONDA_DIR }}\envs\env-fresh" pyinstaller --onefile --console --icon="%root%\AddaxAI\imgs\logo_small_bg.ico" --distpath="%USERPROFILE%\dist" --workpath="%USERPROFILE%\build" "%root%\main.py" | |
# move "%USERPROFILE%\dist\main.exe" "%root%/AddaxAI %RELEASE_VERSION% debug.exe" | |
@REM conda clean | |
call "%conda_exe%" clean --all --yes --force-pkgs-dirs | |
call "%conda_exe%" clean --all --yes | |
call ${{ env.CONDA_DIR }}\condabin\mamba.bat clean --all --yes --force-pkgs-dirs | |
call ${{ env.CONDA_DIR }}\condabin\mamba.bat clean --all --yes | |
call ${{ env.CONDA_DIR }}\condabin\conda.bat clean --all --yes --force-pkgs-dirs | |
call ${{ env.CONDA_DIR }}\condabin\conda.bat clean --all --yes | |
- name: Create archive | |
shell: cmd | |
run: | | |
"C:\Program Files\7-Zip\7z.exe" a -t7z -mx9 "windows-${{ env.RELEASE_VERSION }}.7z" "%USERPROFILE%\AddaxAI\*" | |
- name: Authenticate with Google Cloud | |
uses: google-github-actions/auth@v1 | |
with: | |
credentials_json: ${{ secrets.GOOGLE_STORAGE_UPLOAD_KEY }} | |
- name: Set up Google Cloud | |
uses: google-github-actions/setup-gcloud@v1 | |
with: | |
project_id: github-file-storage | |
# # feb 2025 - disabled to save sapce on github and reduce monthly costs | |
# - name: Upload pinned 7z version to Google Cloud | |
# shell: cmd | |
# run: | | |
# set BUCKET_NAME=${{ env.BUCKET_NAME }} | |
# set PINNED_FOLDER_NAME=${{ env.RELEASE_VERSION }} | |
# set LATEST_FOLDER_NAME=latest | |
# set PINNED_FILE_NAME=windows-${{ env.RELEASE_VERSION }}.7z | |
# set LATEST_FILE_NAME=windows-latest.7z | |
# gsutil cp -r "%PINNED_FILE_NAME%" gs://%BUCKET_NAME%/%PINNED_FOLDER_NAME%/%PINNED_FILE_NAME% | |
- name: Upload latest 7z version to Google Cloud | |
shell: cmd | |
run: | | |
set BUCKET_NAME=${{ env.BUCKET_NAME }} | |
set PINNED_FOLDER_NAME=${{ env.RELEASE_VERSION }} | |
set LATEST_FOLDER_NAME=latest | |
set PINNED_FILE_NAME=windows-${{ env.RELEASE_VERSION }}.7z | |
set LATEST_FILE_NAME=windows-latest.7z | |
gsutil cp -r "%PINNED_FILE_NAME%" gs://%BUCKET_NAME%/%LATEST_FOLDER_NAME%/%LATEST_FILE_NAME% | |
# - name: Get the release body | |
# shell: pwsh | |
# run: Invoke-RestMethod -Uri https://api.github.com/repos/${{ github.repository }}/releases/tags/${{ github.event.release.tag_name }} | ForEach-Object { $_.body } | Out-File -FilePath release_body.txt -Encoding utf8 | |
# - name: Append link to release body | |
# shell: pwsh | |
# run: | | |
# Add-Content -Path "release_body.txt" -Value '- Install for **Windows**: [windows-${{ env.RELEASE_VERSION }}.7z](https://storage.googleapis.com/${{ env.BUCKET_NAME }}/${{ env.RELEASE_VERSION }}/windows-${{ env.RELEASE_VERSION }}.7z)' | |
# - name: Update the release body | |
# shell: cmd | |
# env: | |
# GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
# run: | | |
# @echo off | |
# set RELEASE_NAME=${{ github.ref_name }} | |
# gh release edit %RELEASE_NAME% --notes-file release_body.txt | |
# original code to unzip NSIS without retry mechanism | |
# - name: Install Nsis7z Plugin | |
# run: | | |
# curl --ipv4 --retry 5 -L -o "%GITHUB_WORKSPACE%\Nsis7z_plugin.zip" "https://nsis.sourceforge.io/mediawiki/images/9/93/Nsis7z.zip" | |
# dir "%GITHUB_WORKSPACE%\Nsis7z_plugin.zip" | |
# 7z x -bb3 -o"%GITHUB_WORKSPACE%\NSIS_Plugins" "%GITHUB_WORKSPACE%\Nsis7z_plugin.zip" | |
# shell: cmd | |
- name: Install Nsis7z Plugin | |
run: | | |
@echo off | |
SETLOCAL ENABLEDELAYEDEXPANSION | |
SET MAX_RETRIES=3 | |
SET RETRY_COUNT=0 | |
:retry | |
echo Attempting download and extraction. Try !RETRY_COUNT!... | |
:: Download the file | |
curl --ipv4 --retry 5 -L -o "%GITHUB_WORKSPACE%\Nsis7z_plugin.zip" "https://nsis.sourceforge.io/mediawiki/images/9/93/Nsis7z.zip" | |
dir "%GITHUB_WORKSPACE%\Nsis7z_plugin.zip" | |
:: Try to extract the file | |
7z x -bb3 -o"%GITHUB_WORKSPACE%\NSIS_Plugins" "%GITHUB_WORKSPACE%\Nsis7z_plugin.zip" | |
:: Check if extraction was successful | |
IF %ERRORLEVEL% NEQ 0 ( | |
echo Extraction failed, retrying download... | |
del "%GITHUB_WORKSPACE%\Nsis7z_plugin.zip" | |
SET /A RETRY_COUNT+=1 | |
IF !RETRY_COUNT! LSS %MAX_RETRIES% ( | |
goto retry | |
) ELSE ( | |
echo Failed to download and extract after %MAX_RETRIES% attempts. Exiting. | |
EXIT /B 1 | |
) | |
) ELSE ( | |
echo Extraction succeeded. | |
) | |
ENDLOCAL | |
shell: cmd | |
- name: Install Inetc Plugin | |
run: | | |
curl --ipv4 --retry 5 -L -o "%GITHUB_WORKSPACE%\Inetc_plugin.zip" "https://nsis.sourceforge.io/mediawiki/images/c/c9/Inetc.zip" | |
dir "%GITHUB_WORKSPACE%\Inetc_plugin.zip" | |
7z x -bb3 -o"%GITHUB_WORKSPACE%\NSIS_Plugins" "%GITHUB_WORKSPACE%\Inetc_plugin.zip" | |
shell: cmd | |
- name: Append VERSION and URL to NSIS script | |
shell: cmd | |
run: | | |
echo !define VERSION "${{ env.RELEASE_VERSION }}" > newFile.nsi | |
echo !define URL "https://storage.googleapis.com/${{ env.BUCKET_NAME }}/latest/windows-latest.7z" >> newFile.nsi | |
type "%GITHUB_WORKSPACE%\install_files\windows\nsis-install-compiler.nsi" >> newFile.nsi | |
move /Y newFile.nsi "%GITHUB_WORKSPACE%\install_files\windows\nsis-install-compiler.nsi" | |
- name: Create NSIS installer | |
uses: joncloud/makensis-action@publish | |
with: | |
script-file: "install_files/windows/nsis-install-compiler.nsi" | |
additional-plugin-paths: ${{ github.workspace }}/NSIS_Plugins/Plugins | |
- name: Get Upload URL for Release | |
id: get_release | |
uses: actions/github-script@v6 | |
with: | |
script: | | |
const release = await github.rest.repos.getReleaseByTag({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
tag: '${{ env.RELEASE_VERSION }}', | |
}) | |
// Write the upload URL to the environment file instead of using set-output | |
const fs = require('fs'); | |
fs.appendFileSync(process.env.GITHUB_ENV, `UPLOAD_URL=${release.data.upload_url}\n`); | |
- name: Remove existing asset if present | |
run: | | |
@echo off | |
setlocal | |
REM List all assets in the release using curl | |
curl -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" ^ | |
https://api.github.com/repos/${{ github.repository }}/releases/tags/${{ env.RELEASE_VERSION }} > release_info.json | |
REM Extract asset ID by matching the name | |
for /f "delims=" %%A in ('jq -r ".assets[] | select(.name == \"Windows-installer-${{ env.RELEASE_VERSION }}.exe\") | .id" release_info.json') do set asset_id=%%A | |
echo The asset_id is: %asset_id% | |
REM Check if the asset exists and delete it | |
if not "%asset_id%"=="" ( | |
curl -X DELETE ^ | |
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" ^ | |
https://api.github.com/repos/${{ github.repository }}/releases/assets/%asset_id% | |
) else ( | |
echo Asset not found. Continue with upload... | |
) | |
endlocal | |
shell: cmd | |
- name: Decode PFX certificate from GitHub Secrets | |
run: | | |
$base64String = "${{ secrets.PFX_BASE64_CERTIFICATE }}" | |
[IO.File]::WriteAllBytes("addax_cert.pfx", [Convert]::FromBase64String($base64String)) | |
# # the following is very helpful if you have a new github runner image and want to find signtool.exe | |
# - name: Get signtool.exe location | |
# uses: eltorio/action-signtoolLocation@v1 | |
- name: Sign installer | |
shell: cmd | |
run: | | |
"C:/Program Files (x86)/Windows Kits/10/bin/10.0.26100.0/x64/signtool.exe" sign /f addax_cert.pfx /p "${{ secrets.CODE_SIGN_PASSWORD }}" /tr http://timestamp.digicert.com /td SHA256 /fd SHA256 "${{ github.workspace }}/install_files/windows/AddaxAI-${{ env.RELEASE_VERSION }}-installer.exe" | |
- name: Verify signature | |
shell: cmd | |
run: | | |
"C:/Program Files (x86)/Windows Kits/10/bin/10.0.26100.0/x64/signtool.exe" verify /pa /v "${{ github.workspace }}/install_files/windows/AddaxAI-${{ env.RELEASE_VERSION }}-installer.exe" | |
- name: Remove the PFX file after signing | |
run: | | |
# Check if the .pfx file exists before removal | |
if (Test-Path "addax_cert.pfx") { | |
echo "PFX file exists. Proceeding with removal." | |
Remove-Item -Path "addax_cert.pfx" -Force | |
} else { | |
echo "PFX file does not exist. Skipping removal." | |
} | |
# Check if the .pfx file still exists after removal | |
if (-not (Test-Path "addax_cert.pfx")) { | |
echo "PFX file successfully removed." | |
} else { | |
echo "Failed to remove PFX file." | |
} | |
- name: Upload Asset to GitHub Release | |
uses: actions/upload-release-asset@v1 | |
with: | |
upload_url: ${{ env.UPLOAD_URL }} | |
asset_path: "install_files/windows/AddaxAI-${{ env.RELEASE_VERSION }}-installer.exe" | |
asset_name: "Windows-installer-${{ env.RELEASE_VERSION }}.exe" | |
asset_content_type: application/octet-stream | |
env: | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
- name: Upload installer EXE to Google Cloud | |
shell: cmd | |
run: | | |
set INSTALLER=${{ github.workspace }}/install_files/windows/AddaxAI-${{ env.RELEASE_VERSION }}-installer.exe | |
gsutil cp -r "%INSTALLER%" gs://${{ env.BUCKET_NAME }}/latest/windows-installer-latest.exe |