Skip to content

Release Desktop v2.1 #7

Release Desktop v2.1

Release Desktop v2.1 #7

Workflow file for this run

name: Build & Release
on:
push:
tags:
- 'v*'
workflow_dispatch:
permissions:
contents: write
jobs:
build:
strategy:
matrix:
include:
- os: windows-latest
name: Windows
artifact: BalMasque_Windows
ext: .exe
- os: ubuntu-22.04
name: Linux
artifact: BalMasque_Linux
ext: ""
- os: macos-15-intel
name: Mac_Intel
artifact: BalMasque_Mac_Intel
ext: ""
- os: macos-14
name: Mac_AppleSilicon
artifact: BalMasque_Mac_AppleSilicon
ext: ""
runs-on: ${{ matrix.os }}
name: Build ${{ matrix.name }}
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.11'
- name: Install Linux dependencies
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y python3-tk python3-dev
- name: Install Python dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install pyinstaller
- name: Build with PyInstaller
run: |
if [ "$RUNNER_OS" == "Windows" ]; then
SEP=";"
else
SEP=":"
fi
pyinstaller --onefile --windowed --name "BalMasque" --add-data "logo.png${SEP}." --icon logo.png bal_masque.py
shell: bash
- name: Prepare artifact (Windows)
if: runner.os == 'Windows'
run: |
mkdir release
cp dist/BalMasque.exe release/BalMasque.exe
cp README.md release/
cp LICENSE release/
cd release && 7z a -tzip ../${{ matrix.artifact }}.zip *
shell: bash
- name: Prepare artifact (Linux/Mac)
if: runner.os != 'Windows'
run: |
mkdir release
if [ -d "dist/BalMasque.app" ]; then
cp -r dist/BalMasque.app release/
else
cp dist/BalMasque release/BalMasque
chmod +x release/BalMasque
fi
cp README.md release/
cp LICENSE release/
cd release && tar czf ../${{ matrix.artifact }}.tar.gz *
- name: Upload artifact
uses: actions/upload-artifact@v6
with:
name: ${{ matrix.artifact }}
path: |
${{ matrix.artifact }}.zip
${{ matrix.artifact }}.tar.gz
if-no-files-found: ignore
build-android:
runs-on: ubuntu-latest
name: Build Android APK
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.11'
- name: Set up Java 17
uses: actions/setup-java@v5
with:
distribution: 'temurin'
java-version: '17'
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
build-essential \
git \
zip \
unzip \
autoconf \
libtool \
pkg-config \
zlib1g-dev \
libncurses-dev \
cmake \
libffi-dev \
libssl-dev \
automake \
libltdl-dev \
lld
- name: Install build tools and dependencies
run: |
pip install --upgrade pip setuptools wheel
pip install buildozer cython==3.0.11 virtualenv
- name: Pre-build checks
run: |
echo "── Checking critical source files ──"
for f in bal_masque_mobile.py buildozer.spec logo.png intent_filter.xml; do
if [ ! -f "$f" ]; then
echo "::error::Missing critical file: $f"
exit 1
fi
done
echo "── Checking Python 3 syntax ──"
python -m py_compile bal_masque_mobile.py
echo "── Checking buildozer.spec requirements ──"
grep -q 'pyjnius' buildozer.spec || { echo "::error::pyjnius missing from requirements"; exit 1; }
grep -q 'cython' buildozer.spec || { echo "::error::cython missing from requirements"; exit 1; }
echo "All pre-build checks passed."
- name: Prepare Haar cascades for Android
run: |
mkdir -p cascades
HAAR_DIR=$(python -c "import cv2; print(cv2.data.haarcascades)" 2>/dev/null || echo "")
if [ -z "$HAAR_DIR" ]; then
pip install opencv-python-headless
HAAR_DIR=$(python -c "import cv2; print(cv2.data.haarcascades)")
fi
for xml in haarcascade_frontalface_default.xml haarcascade_frontalface_alt2.xml haarcascade_profileface.xml; do
if [ ! -f "${HAAR_DIR}${xml}" ]; then
echo "::error::Missing cascade file: ${xml}"
exit 1
fi
cp "${HAAR_DIR}${xml}" cascades/
done
echo "Cascades prepared: $(ls cascades/)"
- name: Build APK with Buildozer
run: |
buildozer --verbose android debug 2>&1 || {
echo "::warning::Initial build failed. Applying compatibility patches..."
# Patch 1: pyjnius 'long' type references (Python 2→3)
# TODO: Supprimer lorsque p4a stable intégrera les correctifs Python 3.11.
find .buildozer -type f \( -name '*.pxi' -o -name '*.pyx' \) | while IFS= read -r f; do
if grep -q 'isinstance.*long' "$f" 2>/dev/null; then
echo " Patching long→int in $f"
sed -i 's/isinstance(\([^,]*\), long)/isinstance(\1, int)/g' "$f"
fi
done
find .buildozer -type f -name '*.pyx' -exec cython {} \; 2>/dev/null || true
# Patch 2: numpy C++ missing <unordered_map> header (NDK r25b)
find .buildozer -type f -name 'unique.cpp' -path '*/numpy/*' | while IFS= read -r f; do
if grep -q 'unordered_map' "$f" 2>/dev/null && ! grep -q '#include <unordered_map>' "$f" 2>/dev/null; then
echo " Patching missing #include <unordered_map> in $f"
sed -i '1i #include <unordered_map>' "$f"
fi
done
echo "Retrying build after patches..."
buildozer --verbose android debug
}
timeout-minutes: 90
- name: Verify APK was produced
run: |
APK_COUNT=$(find bin -name '*.apk' 2>/dev/null | wc -l)
if [ "$APK_COUNT" -eq 0 ]; then
echo "::error::No APK file found in bin/ directory"
exit 1
fi
echo "APK produced successfully:"
ls -lh bin/*.apk
- name: Prepare Android artifact
run: |
mkdir -p release-android
cp bin/*.apk release-android/BalMasque.apk
cp README.md release-android/
cp LICENSE release-android/
cd release-android && zip ../BalMasque_Android.zip *
- name: Upload Android artifact
uses: actions/upload-artifact@v6
with:
name: BalMasque_Android
path: BalMasque_Android.zip
- name: Upload build logs on failure
if: failure()
uses: actions/upload-artifact@v6
with:
name: buildozer-logs
path: |
.buildozer/android/platform/**/build.log
.buildozer/android/logs/
if-no-files-found: ignore
verify:
needs: [build, build-android]
runs-on: ubuntu-latest
name: Verify Artifacts
steps:
- name: Download all artifacts
uses: actions/download-artifact@v7
with:
path: artifacts
- name: Verify all platform artifacts exist
run: |
echo "── Artifact verification ──"
MISSING=0
for artifact in BalMasque_Windows BalMasque_Linux BalMasque_Mac_Intel BalMasque_Mac_AppleSilicon BalMasque_Android; do
DIR="artifacts/${artifact}"
if [ ! -d "$DIR" ]; then
echo "::error::Missing artifact directory: ${artifact}"
MISSING=$((MISSING + 1))
continue
fi
FILE_COUNT=$(find "$DIR" -type f \( -name '*.zip' -o -name '*.tar.gz' \) | wc -l)
if [ "$FILE_COUNT" -eq 0 ]; then
echo "::error::No archive found in ${artifact}"
MISSING=$((MISSING + 1))
else
echo "✓ ${artifact}: $(find "$DIR" -type f \( -name '*.zip' -o -name '*.tar.gz' \) -exec basename {} \;)"
fi
done
if [ "$MISSING" -gt 0 ]; then
echo "::error::${MISSING} artifact(s) missing"
exit 1
fi
echo "All artifacts verified."
- name: Verify Android APK integrity
run: |
cd artifacts/BalMasque_Android
unzip -q BalMasque_Android.zip -d apk_check
if [ ! -f apk_check/BalMasque.apk ]; then
echo "::error::BalMasque.apk not found inside archive"
exit 1
fi
APK_SIZE=$(stat --printf="%s" apk_check/BalMasque.apk)
echo "APK size: ${APK_SIZE} bytes"
if [ "$APK_SIZE" -lt 1000000 ]; then
echo "::error::APK is suspiciously small (${APK_SIZE} bytes), possibly corrupt"
exit 1
fi
echo "✓ Android APK integrity check passed"
release:
needs: [build, build-android, verify]
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/v')
steps:
- name: Download all artifacts
uses: actions/download-artifact@v7
with:
path: artifacts
- name: Create Release
uses: softprops/action-gh-release@v2
with:
name: "Bal Masqué ${{ github.ref_name }}"
body: |
## 🎭 Bal Masqué ${{ github.ref_name }}
### Téléchargements
| Plateforme | Fichier |
|---|---|
| 🪟 Windows | `BalMasque_Windows.zip` |
| 🐧 Linux (Ubuntu/Mint) | `BalMasque_Linux.tar.gz` |
| 🍎 macOS (Intel) | `BalMasque_Mac_Intel.tar.gz` |
| 🍎 macOS (Apple Silicon) | `BalMasque_Mac_AppleSilicon.tar.gz` |
| 🤖 Android (APK) | `BalMasque_Android.zip` |
### Installation
**Windows** : Extraire le zip et lancer `BalMasque.exe`
**Linux** :
```bash
tar xzf BalMasque_Linux.tar.gz
chmod +x BalMasque
./BalMasque
```
**macOS** :
```bash
tar xzf BalMasque_Mac_Intel.tar.gz
open BalMasque.app
```
**Android** :
1. Extraire `BalMasque_Android.zip`
2. Installer `BalMasque.apk` (activer "Sources inconnues" dans les paramètres)
3. L'application apparaît dans le menu "Partager avec" pour les images
### Depuis les sources
```bash
pip install -r requirements.txt
python bal_masque.py
```
files: |
artifacts/**/*.zip
artifacts/**/*.tar.gz
draft: false
prerelease: false