Skip to content

AddaxAI v6.02

AddaxAI v6.02 #38

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