Repository navigation
Improve the Debian packaging - #15
Conversation
… pkg-config The build only needs the glib-compile-schemas program, which meson's gnome.post_install() looks up at configure time. It is shipped by libglib2.0-bin in Debian and Ubuntu. Without it, configuration fails with meson 1.7 (trixie) and 1.3 (noble). The headers and the pkg-config file of libglib2.0-dev are not used, and pkg-config was only useful to read the tool path from gio-2.0.pc. libgio-2.0-dev also does not exist in Ubuntu 24.04. Checked by building without pkgconf, libglib2.0-dev and libgio-2.0-dev in Debian sid, Debian trixie with the LMDE 7 repository and Mint 22: meson finds /usr/bin/glib-compile-schemas and all tests pass. Assisted-by: Claude Code:claude-opus-5
The code imports xapp.util and xapp.threading, which python3-xapp only
provides since 3.0.0 ("Add new submodules").
Without the version, the packages can be built and installed against
older python3-xapp versions that are still in the archives, such as
2.4.2-1 in Debian trixie or 2.4.1-1 in Ubuntu 24.04, and fail with "No
module named 'xapp.util'". In Debian trixie 6 of the 7 test modules fail
to import.
Mint 22, LMDE 7 and Debian sid already ship 3.0.2 or later, so nothing
changes there.
Assisted-by: Claude Code:claude-opus-5
The test suite loads modules that use these packages directly, but they
were only pulled in through other dependencies:
- gir1.2-glib-2.0: Gio and GLib (daemon.py, calendar/store.py,
calendar/dbus.py)
- gir1.2-pango-1.0: Pango (agent/agent.py, calendar/views/day_view.py)
- python3-httplib2: imported by clockenstein/networking.py
- tzdata: the tests use zoneinfo.ZoneInfo("Europe/Dublin") and
test_store.py reads /usr/share/zoneinfo/Europe/Dublin
Listing them explicitly keeps the build working if the dependency chains
of other packages change.
Assisted-by: Claude Code:claude-opus-5
Both programs draw widgets from Python, connecting to the GTK "draw"
signal or overriding do_draw() (agent.py, main_window.py, the day, week
and month views and the mini calendar). PyGObject passes the
cairo.Context argument through the gi._gi_cairo module, which is shipped
by python3-gi-cairo, so without that package the drawing callbacks fail.
The package was never listed and was only present because desktop
installations usually have it. With just the current dependencies,
gi.require_foreign("cairo") fails with "No module named 'gi._gi_cairo'"
in Debian sid, Debian trixie with the LMDE 7 repository and Mint 22.
Assisted-by: Claude Code:claude-opus-5
clocks_app.py imports clockenstein.formatting, which imports babel.core, so Clocks needs python3-babel just like Calendar. It was only installed as a dependency of clockenstein-calendar. With clockenstein-clocks installed alone, it fails at startup with "No module named 'babel'" (checked in Debian sid). Assisted-by: Claude Code:claude-opus-5
The notification agent, Calendar and Clocks use Python code shipped in clockenstein-daemon: the clockenstein module in dist-packages (alarms, formatting, drawing, the D-Bus names), and in Calendar's case also store.py, dbus.py and the backends under /usr/share/clockenstein/calendar. They also use the daemon's D-Bus interface. None of these are a stable API between versions. With an unversioned dependency, apt can upgrade one binary package without the others and leave a mismatched set installed. Requiring the same version keeps them in step. Assisted-by: Claude Code:claude-opus-5
…--user The postinst scripts of the daemon and the notification agent run deb-systemd-invoke --user daemon-reload and restart. The --user option was added in init-system-helpers 1.61 and fixed in 1.66 to really reload the user instances. dh_installsystemduser adds the same init-system-helpers (>= 1.66~) dependency to misc:Depends when it generates this code itself, which it only does from compat 14. The unversioned dependency had no effect, because init-system-helpers is Essential: yes. Lintian reports it as an error: depends-on-essential-package-without-using-version. The notification agent also uses deb-systemd-invoke --user but did not declare the dependency at all. In Debian sid all 273 packages that depend on init-system-helpers use a versioned dependency. Debian trixie (1.69) and Ubuntu 24.04 (1.66ubuntu1) already satisfy it. Assisted-by: Claude Code:claude-opus-5
Each binary package now lists what its own files use directly, instead of relying on other packages' dependency chains: - clockenstein-daemon: gir1.2-glib-2.0 (Gio and GLib in daemon.py, store.py and dbus.py), python3-httplib2 (imported by clockenstein/networking.py) and tzdata (zoneinfo in store.py and backends/google.py) - clockenstein-notification-agent: gir1.2-glib-2.0 and gir1.2-pango-1.0 (Gio, GLib and Pango in agent.py) - clockenstein-calendar: gir1.2-glib-2.0 and gir1.2-pango-1.0 (Gio, GLib and Pango in main_window.py, event_dialog.py and the views) - clockenstein-clocks: gir1.2-glib-2.0 (Gio and GLib in clocks_app.py) Until now these were only pulled in through python3-gi, gir1.2-gtk-3.0, python3-googleapi and python3. Assisted-by: Claude Code:claude-opus-5
All four programs use the D-Bus session bus: the daemon owns org.x.clockenstein.Calendar.Service and is D-Bus activated, the notification agent owns its own name and listens to the daemon's signals, and Calendar and Clocks call the daemon and watch its name. Declare it with the virtual packages from Policy's virtual package list, in the form used in Debian sid by 51 of the 54 packages that depend on dbus-session-bus. default-dbus-session-bus is provided by dbus-user-session in Debian sid, Debian trixie and Ubuntu 24.04; dbus-session-bus is also provided by dbus-x11. Assisted-by: Claude Code:claude-opus-5
The Google backend can use accounts configured in GNOME Online Accounts instead of its own OAuth login. It loads the Goa typelib lazily and reports "The gir1.2-goa-1.0 package is missing" when it is not installed, so the feature is optional. gir1.2-goa-1.0 only ships the typelib. Goa.Client also needs the org.gnome.OnlineAccounts service (goa-daemon, from gnome-online-accounts) and the accounts have to be set up somewhere. gnome-online-accounts-gtk provides the configuration tool used outside GNOME and depends on gnome-online-accounts in Debian sid, Debian trixie and Ubuntu 24.04, as well as in the Mint repositories. Assisted-by: Claude Code:claude-opus-5
The CalDAV backend stores account passwords with libsecret (gir1.2-secret-1) in the default collection. libsecret is only a client: without a Secret Service provider on the session bus, passwords cannot be saved and CalDAV accounts fail with "Could not save the password in the keyring". There is no virtual package for a Secret Service provider. Recommend gnome-keyring, the provider used by Mint and the most common choice in Debian sid, while users of other providers can still install without it. Assisted-by: Claude Code:claude-opus-5
The daemon schedules event reminders and alarms, but it only emits them
as D-Bus signals. The notification agent is the only program that shows
them and plays their sounds. Calendar and Clocks both warn when it is
not running ("The notification agent is not running.").
Without the agent, reminders and alarms are silently lost, which is not
what users expect from a default installation. Recommends installs it by
default and still allows installing the daemon without it.
Assisted-by: Claude Code:claude-opus-5
data/meson.build calls gnome.post_install() with gtk_update_icon_cache: true, which looks up gtk4-update-icon-cache or gtk-update-icon-cache at configure time. With meson 1.7 (trixie) and 1.3 (noble), configuration fails when neither is found: "Program 'gtk-update-icon-cache' not found or not executable". Meson 1.12 in sid only warns. The program was only present because gir1.2-gtk-3.0, which is needed only by the tests, pulls it in through the icon theme packages. The package is called gtk-update-icon-cache in Debian sid, Debian trixie and Ubuntu 24.04. It is built from gtk4 in Debian and from gtk+3.0 in Ubuntu 24.04, and either program satisfies meson. Checked with a build that has only debhelper, gettext, meson, python3, libglib2.0-bin and gtk-update-icon-cache installed and the tests disabled: it succeeds in Debian trixie and Mint 22, and fails in Debian trixie without gtk-update-icon-cache. Assisted-by: Claude Code:claude-opus-5
…check> Configuring, building and installing only needs debhelper, gettext, gtk-update-icon-cache, libglib2.0-bin, meson and python3. Everything else in Build-Depends is only imported by the unit tests run by dh_auto_test. Marking those with the nocheck build profile allows building without them when the tests are disabled. Checked in clean chroots of Debian sid, Debian trixie with the LMDE 7 repository and Mint 22. apt-get build-dep --build-profiles=nocheck installs none of the test dependencies, and the build with DEB_BUILD_OPTIONS=nocheck and the nocheck profile succeeds. Its four binary packages have the same control fields and md5sums as a normal build, where all 72 tests pass. Assisted-by: Claude Code:claude-opus-5
Point it to the upstream repository, as done in xapp-symbolic-icons and the other Mint packages. Assisted-by: Claude Code:claude-opus-5
debhelper configures meson with -Dpython.bytecompile=-1 and expects
dh_python3 to handle byte-compilation, but the packaging did not use it.
As a result no .pyc files were ever generated. Python recompiled every
module in memory at each start, since users cannot write to /usr, and
running a program as root (e.g. sudo clockenstein-cli) left __pycache__
directories behind that no package owned and that were not removed with
the packages.
Build-depend on dh-sequence-python3 and add ${python3:Depends} to all
binary packages, as dh_python3 only acts on packages that use it. The
packages now byte-compile their modules in postinst (py3compile), clean
them up in prerm (py3clean) and ship an rtupdate hook for Python version
changes. ${python3:Depends} adds python3:any.
dh_python3 is run twice: the first run handles the public clockenstein
module in dist-packages, the second the private modules under
/usr/share/clockenstein. dh_python3 only scans /usr/share/<package> by
default, which does not match the clockenstein-* package names. With the
private directory alone, the public module is skipped.
Checked in Debian sid (dh-python 7.20260623), Debian trixie with the
LMDE 7 repository (6.20250414) and Mint 22 (6.20240401): the installed
files are unchanged apart from the rtupdate hooks, the existing
maintainer script code is kept, and all tests pass.
Assisted-by: Claude Code:claude-opus-5
The postinst scripts of the daemon and the notification agent reload the user managers and restart the running user services, which debhelper only generates itself from compat 14. Mint 22's debhelper 13.14.1 has no stable compat 14, so the code stays hand-written, but it now matches debhelper's postinst-systemd-user-restart snippet: - only act when systemd is the running init ([ -d /run/systemd/system ]) - also restart on abort-upgrade, abort-deconfigure and abort-remove, so that the services come back after a failed upgrade or removal deb-systemd-invoke --user restart still only restarts services that are running; static units that are not running are not started. Assisted-by: Claude Code:claude-opus-5
The postinst scripts restart the daemon and the notification agent in the running user sessions, but nothing stopped them on removal. Both kept running from deleted files until the users logged out. Add prerm scripts that stop them on remove, matching debhelper's prerm-systemd-user-stop snippet, which it only generates itself from compat 14. Tested in a Debian sid VM with a graphical session and both services running. With the old scripts, removing the packages left both services active with the same PIDs. With the new ones, both are stopped and no process is left. Upgrading still restarts them, reinstalling does not start them when they are stopped, and D-Bus activation of the daemon still works. Assisted-by: Claude Code:claude-opus-5
…d SPDX identifiers - Source pointed to github.com/xapp/clockenstein, the project is at github.com/xapp-project/clockenstein. - data/notification.oga is not GPL-3: it is byte-identical to stereo/dialog-warning.oga from sound-theme-freedesktop, which comes from the Borealis sound theme by Ivica Bukvic. The theme's CREDITS file lists it as "License: CC-BY-SA", and the Debian sound-theme-freedesktop package documents it as CC-BY-SA-3.0. Add a Files stanza for it with the full license text, since /usr/share/common-licenses/CC-BY-SA-3.0 only exists in Debian from base-files 14 and not in trixie or Ubuntu 24.04. - Move the GPL-3 license to a standalone License paragraph and annotate both licenses with their SPDX identifiers (GPL-3.0-only, CC-BY-SA-3.0). The embedded CC-BY-SA-3.0 text matches the SPDX text. cme check dpkg-copyright passes and lintian reports no copyright tags (Debian sid). Assisted-by: Claude Code:claude-opus-5
Bring the lists in line with debian/control: - building needs glib-compile-schemas (libglib2.0-bin) and gtk-update-icon-cache, which meson looks up at configure time and runs on install, and python3, which meson uses at configure time; libglib2.0-dev/libgio-2.0-dev and pkg-config are not needed - add the dependencies the code uses directly (gir1.2-glib-2.0, gir1.2-pango-1.0, python3-httplib2, tzdata, python3-gi-cairo) and the minimum python3-xapp version - name each list after what it is for (building, runtime and tests, runtime only), and add the optional meson test step to the build instructions - mention the D-Bus and systemd user session requirements and the optional packages for CalDAV passwords and GNOME Online Accounts Assisted-by: Claude Code:claude-opus-5
|
I updated the README commit. Looking at the dependency lists again, I wasn't sure they were clear for every user, so now each list is named after what it is for: building, runtime (also needed to run the tests) and other runtime dependencies. I also added |
|
Thanks Fabio, most of it I'd like to merge but there are a few things in there which prevent me and you've asked for feedback also. I'll try to take some time to get back to you on this in the coming days. |
DEs could have their own clockenstein agent. For instance, if we wanted Cinnamon to handle this, it could remind people in a better and more integrated way than the GTK clockenstein-notification-agent does. So I don't think it should be a depend. I think a recommend on the daemon is good for now. When/if DEs start getting their own agents, we can use a virtual package which they all satisfy and depend/recommend on that.
Which DEs are affected and how?
It can be either, I don't really mind, but I don't want to inject licensing in the code. SVGs come from Mint-X but they should be replaced #1.
README sounds good.
I guess. I'd rather not have yet another package name.
PR welcome
PR welcome
PR welcome
Thanks |
|
Thanks for merging and for the answers!
Makes sense, thanks.
It doesn't depend on the DE but on the init system. On distributions that don't use systemd (for example Devuan, or Debian installed with sysvinit or OpenRC),
No headers needed, the README is enough (though per-file notices are what the GPL recommends; with SPDX it would only take a single Right now "GPLv3" without "or later" reads as GPL-3.0-only (section 14 of the GPL), and that's what debian/copyright says too. I'd just make it explicit in the README with the SPDX identifier,
I'll add the sound credit together with the license line.
Agreed, no new package. I'd move the module to a private directory, /usr/share/clockenstein/clockenstein, next to the rest of the code, with the launchers making it importable from there. It's not only about Debian's policy and the package name: a public module also brings other problems, like the one in #17, which came from the
For the clockenstein-clocks description: I'm not very good at writing descriptions, so I asked an LLM for a few options and picked the one that seemed best to me. Would something like this be OK? |
|
@clefebvre I opened #24 ( A few things from my previous comment are still waiting for your answer:
|
Improve the Debian packaging
This reviews the Debian packaging against what the code actually uses, with the goal of improving and making it suitable for Debian too, while keeping it working on Mint 22, LMDE 7 and Mint 23.
Each change is a separate commit with the details in its message. Builds, unit tests and the installed packages (one at a time, without Recommends) were checked in clean chroots of Debian sid, Debian trixie with the LMDE 7 (gigi) repository, and Mint 22 (noble + zena repository). The user service changes were also tested in a Debian sid VM with a graphical session. On a Mint 23 VM (Ubuntu 26.04 +
adrienrepository), the packages were built with the tests, installed, and used in a Cinnamon session: the user services behave as expected, and Calendar and Clocks run without errors.Fixes for real breakage
drawsignal,do_draw()), which needsgi._gi_cairo. It only worked because desktop installations usually have it.clocks_app.py→clockenstein.formatting→babel). With Clocks installed alone it fails at startup.xapp.utilandxapp.threadingonly exist since 3.0.0. Debian trixie (2.4.2) and Ubuntu 24.04 (2.4.1) still have older versions.gnome.post_install()looks up both programs at configure time, and meson 1.3 (noble) and 1.7 (trixie) stop when they are missing.libglib2.0-dev | libgio-2.0-devandpkg-configare not needed (libgio-2.0-devdoes not exist in noble anyway).deb-systemd-invoke --user. This is the same dependency debhelper adds when it generates that code itself (compat 14). The unversioned dependency had no effect, because the package is Essential, and lintian reports it as an error.Explicit dependencies
gir1.2-glib-2.0,gir1.2-pango-1.0,python3-httplib2,tzdata.default-dbus-session-bus | dbus-session-busfor all four packages, which all use the session bus.<!nocheck>. The binary packages built with and without the tests are identical.Recommends and Suggests
clockenstein-notification-agent(was Suggests): without it, reminders and alarms are never shown.gnome-keyring: CalDAV passwords are stored through libsecret, which needs a Secret Service provider.gir1.2-goa-1.0andgnome-online-accounts-gtkfor Google accounts from GNOME Online Accounts.Other packaging improvements
Homepage field pointing to the repository.
dh_python3: debhelper tells meson not to byte-compile and expects dh_python3 to do it, but it was not used. So no
.pycfiles were ever generated, and running a program as root left__pycache__directories that were not removed with the packages. The packages now byte-compile their modules on install, clean them up on removal, and follow Python version changes.User services:
abort-*);Compat 14 would generate this code itself, but Mint 22's debhelper has no stable compat 14, so it stays hand-written.
debian/copyright:
github.com/xapp/clockenstein;data/notification.ogais not GPL-3: it isdialog-warning.ogafrom sound-theme-freedesktop (Borealis sound theme by Ivica Bukvic, CC-BY-SA-3.0);README: the dependency lists now match
debian/control.Notes and questions for other improvements, not only related to packaging
Clocks without the agent: alarms don't ring without the notification agent ("Alarms will not ring."), but Clocks only gets it through the daemon's Recommends. Should Clocks depend on it directly, or recommend it?
Autostart: the autostart files run
systemctl --user start ..., so the agent doesn't start in sessions without a systemd user instance, for example when the session bus comes from dbus-x11. Is that intended?License:
Sound attribution: CC-BY-SA requires crediting the author of
data/notification.oga; it is now indebian/copyright, but it should probably also be mentioned in the README or the about dialog.Public Python module: the
clockensteinmodule is installed indist-packagesfromclockenstein-daemon. Debian's Python policy expects public modules inpython3-*packages; a private directory (like the rest of the code in/usr/share/clockenstein) would avoid that.Description: lintian finds the long description of
clockenstein-clockstoo short.AppStream: there is no metainfo file for Calendar and Clocks, which software managers use to list applications.
.gitignore does not cover the
obj-*/build directory created by debhelper.python3-xapp packaging:
xapp/SettingsWidgets.pyuses the XApp, Gtk and Gdk typelibs, but thepython3-xapppackage in the Mint repositories only depends onpython3-psutil. As a result, Clocks fails with "Namespace XApp not available" whengir1.2-xapp-1.0is not installed. The Debian package already declares these since 3.0.2-1 (gir1.2-glib-2.0,gir1.2-gtk-3.0,gir1.2-pango-1.0,gir1.2-xapp-1.0,python3-gi); the same fix would be needed in python3-xapp'sdebian/control. This PR does not work around it. EDIT: fixed in debian: packaging improvements from the Debian package linuxmint/python3-xapp#25