feat: GUI installers for OnTrack Python and OnTrack-RS #5
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
| name: OnTrack CI — Linux · Windows · Android | |
| on: | |
| push: | |
| paths: | |
| - "ontrack/**" | |
| - ".github/workflows/ontrack-ci.yml" | |
| pull_request: | |
| paths: | |
| - "ontrack/**" | |
| defaults: | |
| run: | |
| working-directory: ontrack | |
| # ────────────────────────────────────────────────────────────────────────── | |
| # JOB 1: Linux x86_64 (unit tests + PyInstaller smoke build) | |
| # ────────────────────────────────────────────────────────────────────────── | |
| jobs: | |
| linux: | |
| name: "Linux x86_64" | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python 3.11 | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.11" | |
| cache: pip | |
| cache-dependency-path: ontrack/requirements.txt | |
| - name: Install system deps (Tk + display) | |
| run: | | |
| sudo apt-get update -qq | |
| sudo apt-get install -y python3-tk xvfb libgl1 | |
| - name: Install Python deps | |
| run: pip install -r requirements.txt pytest pytest-mock pytest-cov | |
| - name: Run unit tests (all marks) | |
| run: | | |
| pytest tests/ -v --tb=short \ | |
| -m "linux or android" \ | |
| --cov=core --cov=config \ | |
| --cov-report=term-missing \ | |
| --cov-report=xml:coverage-linux.xml | |
| - name: Upload coverage | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: coverage-linux | |
| path: ontrack/coverage-linux.xml | |
| - name: PyInstaller smoke build (no GUI window) | |
| # Runs headless; --onefile --noconsole verifies the spec compiles. | |
| # We use xvfb-run in case any import touches Tk at collect time. | |
| run: | | |
| xvfb-run --auto-servernum pyinstaller \ | |
| --onefile --noconsole \ | |
| --name ontrack-linux \ | |
| main.py | |
| continue-on-error: true # build failure is reported, not fatal in PR | |
| - name: Upload Linux binary | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ontrack-linux | |
| path: ontrack/dist/ontrack-linux | |
| if-no-files-found: warn | |
| # ────────────────────────────────────────────────────────────────────────── | |
| # JOB 2: Windows 11 (unit tests + PyInstaller smoke build) | |
| # ────────────────────────────────────────────────────────────────────────── | |
| windows: | |
| name: "Windows 11 (x86_64)" | |
| runs-on: windows-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python 3.11 | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.11" | |
| cache: pip | |
| cache-dependency-path: ontrack/requirements.txt | |
| - name: Install Python deps | |
| run: pip install -r requirements.txt pytest pytest-mock pytest-cov | |
| - name: Run unit tests (windows mark) | |
| run: | | |
| pytest tests/ -v --tb=short ` | |
| -m "windows or linux" ` | |
| --cov=core --cov=config ` | |
| --cov-report=term-missing ` | |
| --cov-report=xml:coverage-windows.xml | |
| - name: Upload coverage | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: coverage-windows | |
| path: ontrack/coverage-windows.xml | |
| - name: PyInstaller smoke build | |
| run: | | |
| pyinstaller ` | |
| --onefile --noconsole ` | |
| --name ontrack-windows ` | |
| main.py | |
| continue-on-error: true | |
| - name: Upload Windows binary | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ontrack-windows | |
| path: ontrack/dist/ontrack-windows.exe | |
| if-no-files-found: warn | |
| # ────────────────────────────────────────────────────────────────────────── | |
| # JOB 3: Android buildozer config validation (no emulator needed) | |
| # | |
| # This job: | |
| # a) runs the Android-marked pytest checks (config, imports, spec) | |
| # b) attempts a buildozer dry-run to validate the spec parses correctly | |
| # c) does NOT produce an APK (that requires NDK ~10 GB — use self-hosted) | |
| # ────────────────────────────────────────────────────────────────────────── | |
| android-validate: | |
| name: "Android config validation" | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python 3.11 | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.11" | |
| - name: Install test deps (no full build chain needed for config checks) | |
| run: pip install pytest pytest-mock requests geopy pandas openpyxl python-dotenv | |
| - name: Install buildozer (spec parsing only) | |
| run: pip install buildozer | |
| - name: Run Android compat checks | |
| run: pytest tests/ -v --tb=short -m android | |
| - name: Buildozer spec parse (dry-run) | |
| # buildozer --help exits 0 even without NDK; what we want is that | |
| # parsing buildozer.spec does not raise a ConfigError. | |
| run: | | |
| python - <<'PYEOF' | |
| import sys | |
| try: | |
| from buildozer import Buildozer | |
| b = Buildozer() | |
| print("buildozer.spec parsed OK") | |
| print(f" title : {b.config.get('app', 'title')}") | |
| print(f" package : {b.config.get('app', 'package.name')}") | |
| print(f" version : {b.config.get('app', 'version')}") | |
| print(f" android.api: {b.config.get('app', 'android.api')}") | |
| print(f" requirements: {b.config.get('app', 'requirements')}") | |
| except Exception as e: | |
| print(f"buildozer.spec parse ERROR: {e}", file=sys.stderr) | |
| sys.exit(1) | |
| PYEOF | |
| - name: Summarize Android readiness | |
| if: always() | |
| run: | | |
| echo "=== Android Build Readiness Summary ===" | |
| echo "" | |
| echo "✓ buildozer.spec parsed without errors" | |
| echo "✓ Android compat pytest checks completed" | |
| echo "" | |
| echo "To perform a full APK build, run on a self-hosted runner" | |
| echo "with the Android SDK/NDK pre-installed, or use:" | |
| echo " buildozer android debug" | |
| echo "" | |
| echo "Known blockers (see test output above):" | |
| echo " • customtkinter/Tkinter in gui/ must be replaced with Kivy" | |
| echo " • ortools must be replaced with a p4a-compatible solver" | |
| # ────────────────────────────────────────────────────────────────────────── | |
| # JOB 4: Full APK build (self-hosted / manual trigger only) | |
| # | |
| # Uncomment and configure a self-hosted runner with Android SDK to use. | |
| # ────────────────────────────────────────────────────────────────────────── | |
| # android-apk: | |
| # name: "Android APK (self-hosted)" | |
| # runs-on: [self-hosted, linux, android-sdk] | |
| # needs: android-validate | |
| # if: github.event_name == 'workflow_dispatch' | |
| # steps: | |
| # - uses: actions/checkout@v4 | |
| # - name: Build APK | |
| # run: buildozer android debug | |
| # - name: Upload APK | |
| # uses: actions/upload-artifact@v4 | |
| # with: | |
| # name: ontrack-apk | |
| # path: ontrack/bin/*.apk |