diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 326a705..1131929 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -18,8 +18,9 @@ jobs: strategy: fail-fast: false matrix: - # NOTE: Testing of the Windows targets are currently disabled because - # the test script is simply not ready for it. + # NOTE: Full testsuite on Windows is disabled because the test script + # requires Linux kernel source tree. However, headless mode tests + # are now enabled for Windows. target: # Python 3.12 - python: '3.12' @@ -28,9 +29,10 @@ jobs: - python: '3.12' os: macOS builder: macos-15 - # - python: '3.12' - # os: Windows - # builder: windows-2022 + - python: '3.12' + os: Windows + builder: windows-2022 + headless-only: true steps: - name: Set up environment @@ -58,6 +60,8 @@ jobs: pip install --user setuptools wheel - name: Check out Linux source code + # Skip for Windows (headless-only mode) + if: ${{ matrix.target.headless-only != true }} uses: actions/checkout@v5 # On Windows, checkout of 'aux.c' is expected to fail because ... Windows. continue-on-error: true @@ -68,12 +72,43 @@ jobs: - name: Check out Kconfiglib source code uses: actions/checkout@v5 with: - path: Kconfiglib + # Windows (headless-only): checkout to root directory + # Linux/macOS (full test): checkout to Kconfiglib subdirectory + path: ${{ matrix.target.headless-only && '.' || 'Kconfiglib' }} - name: Apply Linux Kconfig Makefile patch + # Skip for Windows (headless-only mode) + if: ${{ matrix.target.headless-only != true }} run: | git apply Kconfiglib/makefile.patch - name: Run testsuite + # Skip for Windows (headless-only mode) + if: ${{ matrix.target.headless-only != true }} run: | Kconfiglib/tests/reltest python + + - name: Test headless mode + # Use root dir for Windows, Kconfiglib subdir for Linux/macOS + working-directory: ${{ matrix.target.headless-only && '.' || 'Kconfiglib' }} + run: | + python << 'EOF' + from kconfiglib import Kconfig + import menuconfig + print('Testing headless mode...') + kconf = Kconfig('examples/Kmenuconfig') + menuconfig.menuconfig(kconf, headless=True) + print('Headless mode test passed') + EOF + + - name: Install windows-curses (Windows only) + if: matrix.target.os == 'Windows' + run: | + pip install windows-curses + + - name: Test menuconfig import (Windows Python 3.12) + if: matrix.target.os == 'Windows' + # Use root dir for Windows (headless-only mode) + working-directory: ${{ matrix.target.headless-only && '.' || 'Kconfiglib' }} + run: | + python -c "import menuconfig; print('menuconfig import successful')" diff --git a/menuconfig.py b/menuconfig.py index ff1224d..f4aed51 100755 --- a/menuconfig.py +++ b/menuconfig.py @@ -729,15 +729,22 @@ def _main(): menuconfig(standard_kconfig(__doc__)) -def menuconfig(kconf): +def menuconfig(kconf, headless=False): """ Launches the configuration interface, returning after the user exits. kconf: Kconfig instance to be configured + + headless: + If True, run in headless mode without launching the terminal interface. + This is useful for testing, CI/CD pipelines, and automated configuration + processing. In headless mode, the function only loads the configuration + and returns immediately without user interaction. """ # Import curses at runtime to avoid issues in headless environments - _ensure_curses() + if not headless: + _ensure_curses() global _kconf global _conf_filename @@ -785,6 +792,10 @@ def menuconfig(kconf): if _CHANGE_C_LC_CTYPE_TO_UTF8: _change_c_lc_ctype_to_utf8() + # In headless mode, just load the configuration and return + if headless: + return + # Get rid of the delay between pressing ESC and jumping to the parent menu, # unless the user has set ESCDELAY (see ncurses(3)). This makes the UI much # smoother to work with.