Skip to content

Add native Linux and AppImage support - #352

Merged
zaktherobot merged 10 commits into
tommadness:masterfrom
Zexyen:linux-port
Aug 3, 2026
Merged

Add native Linux and AppImage support#352
zaktherobot merged 10 commits into
tommadness:masterfrom
Zexyen:linux-port

Conversation

@Zexyen

@Zexyen Zexyen commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds Linux support for running from source and distributing the seed generator as a self-updating AppImage.

Changes

  • Add shared platform, path, desktop, and external-tool handling in Module/platformutils.py.
  • Add a Linux/AppImage entry point and platform-aware release updates through linux_main.py and UI/GithubInfo/releaseInfo.py.
  • Add AppImage packaging under packaging/linux and an Ubuntu 22.04 build, smoke test, artifact, and release workflow in .github/workflows/build-appimage.yml.
  • Store mutable Linux application data in the XDG data directory instead of the process launch directory.
  • Resolve OpenKH tools in this order on Linux: native executable, .NET DLL, then Windows executable through Wine. Also support Wine-style config paths and the Avalonia Mods Manager layout.
  • Fix checkbox persistence under PySide6 6.x by using the boolean toggle signal in UI/Submenus/SubMenu.py. This is needed for reliable Linux settings and is a cross-platform compatibility fix.
  • Harden self-updates with exact release asset matching, HTTP and download-size validation, safe temporary-file cleanup, and atomic replacement.
  • Add Linux/Windows CI tests and a Windows PyInstaller packaging check. Release uploads run separately with narrowly scoped write permission, and release builds explicitly check out the published tag.
  • Document Linux source and AppImage usage in README.md.
  • Set the development version to 3.4.0-beta.

Validation

  • AppImage CI builds on Ubuntu 22.04 and launches the application headlessly as a smoke test.
  • Verified checkbox-backed settings remain enabled under PySide6 6.x.
  • Verified platform-specific update selection and OpenKH native/.NET/Wine command resolution.
  • Added focused tests for Linux data paths, Wine path conversion, OpenKH launcher fallback, release asset selection, truncated update handling, and checkbox persistence.
  • CI runs focused Linux-port regression tests on Ubuntu and Windows and validates the Windows PyInstaller specification.

Runtime notes

  • Source execution requires Python 3.12+.
  • Clipboard support may require wl-clipboard, xclip, or xsel; some distributions also require Qt xcb libraries.
  • OpenKH-dependent features require a native OpenKH tool, .NET, or Wine. Other generator features do not require Wine.
  • AppImage self-update only applies when running inside an AppImage.
  • Mutable Linux data is stored under $XDG_DATA_HOME/kh2randomizer, defaulting to ~/.local/share/kh2randomizer.
  • CI uses EXTRACTED_DATA_URL when configured; otherwise it extracts extracted_data.zip from the latest upstream Windows release.

Additional Notes

  • There is also a pending Draft PR for OpenKH to Port the WPF UI over to Avalonia, as well as adding native Linux Support on that end.

Zexyen added 9 commits July 15, 2026 21:29
- Fix all checkbox settings silently storing False: stateChanged emits an
  int, which no longer compares equal to Qt.Checked (a pure Python enum in
  PySide6 6.4+); use toggled(bool) instead. Building the UI was resetting
  every checked toggle (Critical Bonuses, music rando, etc.) to off.
- Run OpenKH tools natively on Linux: prefer a native binary, then the
  framework-dependent .dll via dotnet --roll-forward, then wine as a
  last resort.
- Translate Wine-style Z:\ paths when reading config files (OpenKH's
  mods-manager.yml gameDataPath written by tools that ran under Wine).
- Accept OpenKh.Tools.ModsManager.Avalonia as a valid OpenKH folder marker.
Builds on ubuntu-22.04 for an older glibc floor, obtains extracted_data.zip
from the upstream release exe (or an EXTRACTED_DATA_URL repo variable),
smoke-tests the result headless, uploads it as an artifact, and attaches
it to releases as KH2.Randomizer-x86_64.AppImage - the exact asset name
the Linux auto-updater looks for.
Stores mutable app data in a stable writable directory on Linux, avoiding AppImage and launch-location write issues.

Tightens release asset matching and download validation, and separates AppImage release uploads into a dedicated workflow job with pinned actions and verified tooling.
Installs the minimal desktop libraries needed for GUI-related tests to run reliably on Linux CI.

Also bumps a Windows-only dependency patch release to keep the locked environment current.
Adds the missing runtime dependency needed by the updated test path and narrows CI verification to the affected test modules.

Also updates the checkbox settings test to use the current submenu helper, keeping the regression coverage aligned with the latest API.

@zaktherobot zaktherobot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey,

Thanks so much for going through the effort of extending the compatibility to other platforms! I see that most of the changes are (str,Enum) to (StrEnum) and then the additional wrappers around the file handling touch points. All that looks fine to me, I had just a couple small asks that if you could follow up with, it'd be awesome, and I'll probably merge this straight away.

And as a side note, it looks like the AppImage artifact would need to be put on the releases. Would you be willing to build those images when we make those releases? Or should I invest in setting up an environment myself for that? No worries either way, and thanks again for your work!

-Zak

Comment thread Module/version.py Outdated
import os

LOCAL_UI_VERSION = '3.3.0-beta'
LOCAL_UI_VERSION = '3.4.0-beta'

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3.3.0 hasn't been publicly released yet, so no need to bump the version number here.

Comment thread UI/worker.py Outdated
elif custom_file_path.suffix.lower() == ".sh":
subprocess.call(["/bin/sh", str(custom_file_path)], cwd=custom_cwd)
else:
raise GeneratorException(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be a different exception type. GeneratorException is usually triggered by the randomization process, not from a system level call to external executables. It's probably fine, since it's a minor thing, but if you get around to it, maybe a new exception type for this would be better.

Improves error handling when a generated mod tries to run a non-executable file, so the failure is reported separately from generator errors.

Also restores the UI version string to the previous beta release.
@Zexyen

Zexyen commented Aug 3, 2026

Copy link
Copy Markdown
Contributor Author

Hey Zak!

I'd be perfectly willing to Build the images myself, or I can adjust the workflow to attach the images on tagged releases.

I've also gone ahead & added a new exception type ExternalExecutableException and reverted the UI Versioning.

@zaktherobot
zaktherobot merged commit 7390c8c into tommadness:master Aug 3, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants