pythonopenglkivygithub-actionspytest

How does one test a Kivy App on GitHub actions MacOS Runner?


I am trying to use GitHub actions to test my Kivy application on various operating systems. I am having trouble however running the app on MacOS operating systems and keep getting this error:

INFO     kivy:__init__.py:67 Window: Provider: sdl2
CRITICAL kivy:__init__.py:99 Window: Unable to find any valuable Window provider. Please enable debug logging (e.g. add -d if running from the command line, or change the log level in the config) and re-run your app to identify potential causes
sdl2 - RuntimeError: b'Failed creating OpenGL pixel format'
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/kivy/core/__init__.py", line 71, in core_select_lib
    cls = cls()
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/kivy/core/window/window_sdl2.py", line 165, in __init__
    super(WindowSDL, self).__init__()
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/kivy/core/window/__init__.py", line 1129, in __init__
    self.create_window()
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/kivy/core/window/window_sdl2.py", line 316, in create_window
    self.system_size = self._win.setup_window(
  File "kivy/core/window/_window_sdl2.pyx", line 243, in kivy.core.window._window_sdl2._WindowSDL2Storage.setup_window
  File "kivy/core/window/_window_sdl2.pyx", line 76, in kivy.core.window._window_sdl2._WindowSDL2Storage.die

I am able to get it working on windows and linux runners. Does GitHub's MacOS runner not support OpenGL or is there a way to resolve this?

My test application is:

from kivy.uix.label import Label
from kivy.app import App


class SimpleApp(App):
    def __init__(self, **kwargs):
        super(SimpleApp, self).__init__(**kwargs)
        self.text = "Hello World"

    def build(self):
        return Label(text=self.text)


if __name__ == '__main__':
    SimpleApp().run()

My testing code is:

import unittest
import time
from functools import partial
from kivy.clock import Clock

from simpleapp import SimpleApp


class Test(unittest.TestCase):

    def pause(*args):
        time.sleep(0.000001)

    def run_test(self, app, *args):
        self.assertEqual(app.text, "Hello World")
        app.stop()

    def test_example(self):
        app = SimpleApp()
        p = partial(self.run_test, app)
        Clock.schedule_once(p, 0.000001)
        app.run()


if __name__ == '__main__':
    unittest.main()

And my workflow file is:

name: Python application

on:
  push:
    branches: [ "master" ]
  pull_request:
    branches: [ "master" ]
  workflow_dispatch:

permissions:
  contents: read

jobs:
  mac_test:

    runs-on: macos-latest

    steps:
      - uses: actions/checkout@v4
      - name: Set up Python 3.10
        uses: actions/setup-python@v4
        with:
          python-version: "3.10"
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          python -m pip install kivy pytest
      - name: Test App
        run: |
          python -m pytest

Solution

  • This happens because kivy now uses ANGLE backend for OpenGL on MacOS and no longer includes an OpenGL build in the kivy wheels. On some MacOS virtual machines, like those that the GitHub Actions runners use, the necessary Metal APIs are not present. This leads to the inability to find a window provider when running your Kivy app on MacOS with the shared GitHub Actions runners.

    One way I've managed to get around this is to install kivy from source (tell pip not to use binary wheels) and to use a software OpenGL provider (one such provider that kivy can use is pygame). You can adjust your GitHub workflow Install dependencies step as follows:

          - name: Install dependencies
            env:
              USE_ANGLE_GL_BACKEND: "0"
            run: |
              python -m pip install --upgrade pip
              python -m pip install pytest pygame
              python -m pip install "kivy[base]" --no-binary kivy
    

    However, while this configuration works (at least in this limited example), it is not supported by Kivy (because it has been deprecated by Apple). They only officially support the Angle GL backend now.


    It is possible to virtualize MacOS with Angle/Metal support (as parallels and VMware do, anyhow), but it's unclear to me if this is possible with the GitHub Actions VMs specifically. Last I could find (Feb 2023) a GitHub employee stated this was not possible with their MacOS virtualization strategy, though the details are unclear.

    Related:

    Other options to workaround this limitation would be to use a self-hosted MacOS runner with Metal capabilities available.