Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 49 additions & 25 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ concurrency:
# READ THIS BEFORE TRUSTING A GREEN TICK.
#
# What CI proves is strictly LESS than what `./verify.sh --full` proves on a
# real machine. Green here means: the code lints, the pure-Python tier passes,
# the packaging is well-formed, and the widgets build under GTK 4 / libadwaita.
# real machine. Green here means: the code lints, the packaging is well-formed,
# and the suite passes against a GNOME 50 userspace with a private session bus.
#
# It does NOT prove any of the following, all of which only the local canonical
# check covers:
Expand All @@ -27,61 +27,85 @@ concurrency:
# * that the machine this was built on came out unchanged (F16).
# A change that is green here and has not been through ./verify.sh --full is
# unverified. See docs/testing.md.
#
# WHY THE WHOLE SUITE RUNS IN THE ARCH CONTAINER AND NOT ON THE UBUNTU RUNNER.
# It was split the other way until the v2 rebuild, and the unit half could not
# pass there for three separate reasons, none of them about the code:
# * with no PyGObject the page modules will not import, and the tests that
# read a setting through GioBackend have nothing to read it with;
# * with PyGObject but no session bus, every settings write is skipped with
# "your desktop session wasn't running" — 19 failures that say nothing;
# * with both, ubuntu-24.04's gsettings-desktop-schemas is GNOME 46, which
# has no `accent-color` key and no org.gnome.shell, so a further 14 fail
# for being a 2024 desktop rather than a 2026 one.
# The container is the machine gtheme targets. The ubuntu job keeps the two
# things that genuinely do not need a desktop: the linter and the packaging.
jobs:
lint-and-unit:
name: ruff + unit tests
lint-and-packaging:
name: ruff + packaging
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
# F10: core/ may import Gio/GLib (a guard test forbids Gtk/Adw there), so
# the unit tier needs PyGObject with the GLib typelib. libglib2.0-bin
# provides glib-compile-schemas, which the settings-backend tests use to
# build a throwaway schema. The last three are what the packaging tests
# check the launcher entry, the store listing and the icons with — without
# them those tests skip themselves and prove nothing.
- name: Install GLib bindings and the packaging checkers
# These three are what the packaging tests check the launcher entry, the
# store listing and the icons with — without them those tests skip
# themselves and prove nothing. No PyGObject here on purpose: nothing in
# this job may need a desktop.
- name: Install the packaging checkers
run: |
sudo apt-get update
sudo apt-get install -y python3-gi gir1.2-glib-2.0 libglib2.0-bin \
desktop-file-utils appstream librsvg2-bin
sudo apt-get install -y desktop-file-utils appstream librsvg2-bin
- name: Install gtheme
run: |
python -m venv --system-site-packages .venv
python -m venv .venv
.venv/bin/python -m pip install --upgrade pip
.venv/bin/python -m pip install -e '.[dev]'
- name: ruff
run: .venv/bin/ruff check .
- name: pytest
# Ubuntu runners ship libadwaita 1.5; gtheme targets 1.9. No Adw code
# may run here — that is the archlinux job's task. The unit tier
# includes tests/unit/test_packaging_*.py, which builds a real wheel
# and looks inside it.
run: .venv/bin/python -m pytest -q -m "not gtk and not sandbox"
- name: pytest — packaging only
# Builds a real wheel and looks inside it, validates the .desktop file
# and the metainfo, and checks what install.sh would put where.
run: |
.venv/bin/python -m pytest -q \
tests/unit/test_packaging_wheel.py \
tests/unit/test_packaging_desktop.py \
tests/unit/test_packaging_install.py

gtk:
name: GTK/libadwaita tests (Arch container)
tests:
name: the suite (Arch container, GNOME 50)
runs-on: ubuntu-latest
container: archlinux:latest
steps:
# The GNOME lines are not decoration. Without them ten tests fail for the
# container rather than for the code: the schemas the pages read
# (org.gnome.shell, org.gnome.mutter, the settings-daemon plugins), the
# GnomeDesktop-4.0 typelib the thumbnailer needs, and the wallpaper
# catalogue under /usr/share/gnome-background-properties.
- name: Install system packages
run: |
pacman -Syu --noconfirm \
python python-gobject gtk4 libadwaita glib2 dconf libsoup3 \
gsettings-desktop-schemas gnome-desktop-4 gnome-settings-daemon \
mutter gnome-shell gnome-backgrounds \
desktop-file-utils appstream \
python-pip python-hatchling dbus git
- uses: actions/checkout@v4
- name: Install gtheme
run: |
python -m venv --system-site-packages .venv
.venv/bin/python -m pip install -e '.[dev]'
- name: pytest -m gtk
- name: pytest
# gtk4-broadwayd is an offscreen GDK backend: no X server, no
# compositor, no Xvfb needed. dbus-run-session gives the tests a
# private session bus so nothing reaches a real one.
# private session bus so nothing reaches a real one — and so that the
# transaction tests have a session to write into at all.
#
# -m "not sandbox" is both tiers at once: the sandbox tier is the only
# one this file refuses to run, and pyproject already deselects it.
run: |
gtk4-broadwayd :5 &
sleep 2
GDK_BACKEND=broadway BROADWAY_DISPLAY=:5 \
dbus-run-session -- .venv/bin/python -m pytest -q -m gtk
dbus-run-session -- .venv/bin/python -m pytest -q -m "not sandbox"
46 changes: 35 additions & 11 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,27 +18,49 @@ permissions:
contents: read

jobs:
# Nothing ships that the suite has not passed on, and the suite needs a
# GNOME 50 userspace and a session bus to mean anything — see the long note
# at the top of ci.yml. This is that job, and the wheel waits for it.
tests:
name: the suite (Arch container, GNOME 50)
runs-on: ubuntu-latest
container: archlinux:latest
steps:
- name: Install system packages
run: |
pacman -Syu --noconfirm \
python python-gobject gtk4 libadwaita glib2 dconf libsoup3 \
gsettings-desktop-schemas gnome-desktop-4 gnome-settings-daemon \
mutter gnome-shell gnome-backgrounds \
desktop-file-utils appstream \
python-pip python-hatchling dbus git
- uses: actions/checkout@v4
- name: Install gtheme
run: |
python -m venv --system-site-packages .venv
.venv/bin/python -m pip install -e '.[dev]'
- name: Test before shipping
run: |
gtk4-broadwayd :5 &
sleep 2
GDK_BACKEND=broadway BROADWAY_DISPLAY=:5 \
dbus-run-session -- .venv/bin/python -m pytest -q -m "not sandbox"

build:
needs: tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.13"

# Same reason as ci.yml: core/ imports Gio, so the unit tier needs the
# GLib bindings even though no window is ever opened here.
- name: Install GLib bindings
# The wheel is pure Python; only the launcher entry and the store listing
# need checking here, and neither needs a desktop.
- name: Install the packaging checkers
run: |
sudo apt-get update
sudo apt-get install -y python3-gi gir1.2-glib-2.0 libglib2.0-bin \
desktop-file-utils appstream

- name: Test before shipping
run: |
python -m venv --system-site-packages .venv
.venv/bin/python -m pip install -e '.[dev]'
.venv/bin/python -m pytest -q -m "not gtk and not sandbox"
sudo apt-get install -y desktop-file-utils appstream

- name: Check the launcher entry and the store listing
run: |
Expand All @@ -47,6 +69,8 @@ jobs:

- name: Build the wheel
run: |
python -m venv .venv
.venv/bin/python -m pip install -e '.[dev]'
.venv/bin/python -m pip install build
.venv/bin/python -m build --wheel

Expand Down
5 changes: 5 additions & 0 deletions tests/unit/test_applyrunner.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@

pytestmark = pytest.mark.gtk

# A marker deselects after collection, so ``-m "not gtk"`` cannot save a
# machine with no PyGObject from the module-scope import below: without this
# line the whole run aborts on a collection error instead of skipping.
pytest.importorskip("gi", reason="PyGObject is needed for these widgets")

from gtheme.ui.applyrunner import ApplyRunner # noqa: E402


Expand Down
5 changes: 5 additions & 0 deletions tests/unit/test_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@

pytestmark = pytest.mark.gtk

# A marker deselects after collection, so ``-m "not gtk"`` cannot save a
# machine with no PyGObject from the module-scope import below: without this
# line the whole run aborts on a collection error instead of skipping.
pytest.importorskip("gi", reason="PyGObject is needed for these widgets")

from gi.repository import Adw, Gtk # noqa: E402

from gtheme import window as window_module # noqa: E402
Expand Down
Loading