diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml index e5da45f..bd5ac15 100644 --- a/.github/workflows/packages.yml +++ b/.github/workflows/packages.yml @@ -251,6 +251,47 @@ jobs: test ! -e stage/usr/libexec/hyprcosmic echo "staged files: $(find stage -type f | wc -l)" + # Checked here, once, rather than in each of the three packaging recipes, + # and not with desktop-file-validate. + # + # desktop-file-validate rejects DesktopNames -- "keys extending the format + # should start with X-" -- because the Desktop Entry Specification + # registers keys for application launchers, and these are session files. + # DesktopNames is what a display manager reads to set XDG_CURRENT_DESKTOP, + # so the session needs it. cosmic.desktop is upstream cosmic-session's + # file, unchanged here apart from the Exec path, and the copy Fedora ships + # as cosmic-session-1.5.0-1.fc44 fails the identical check: the validator + # has no entry for the key, and every distribution ships the file anyway. + # + # What the validator would not have caught is the failure that actually + # matters: an Exec naming a binary this package does not install puts an + # entry on the greeter's menu that dies silently when chosen. So that is + # what is checked, against the tree about to be packaged. + - name: Check the session entries + run: | + set -eu + for f in stage/usr/share/wayland-sessions/*.desktop; do + echo "== $f" + cat "$f" + test "$(sed -n 1p "$f")" = '[Desktop Entry]' || { + echo "$f: first line is not [Desktop Entry]" >&2; exit 1; } + for key in Name Type Exec DesktopNames; do + grep -q "^${key}=" "$f" || { echo "$f: no $key=" >&2; exit 1; } + done + grep -qx 'Type=Application' "$f" || { + echo "$f: Type is not Application; a greeter will ignore it" >&2; exit 1; } + exec_path=$(sed -n '0,/^Exec=/s/^Exec=//p' "$f" | cut -d' ' -f1) + case $exec_path in + /*) ;; + *) echo "$f: Exec=$exec_path is not absolute" >&2; exit 1 ;; + esac + test -x "stage${exec_path}" || { + echo "$f: Exec=$exec_path is not an executable this package installs" >&2 + exit 1 + } + echo " Exec -> stage${exec_path} ok" + done + # ---- Fedora ------------------------------------------------------- # # The file list is generated rather than written into the spec. Across 27 @@ -325,7 +366,11 @@ jobs: # dependencies without touching the filesystem, and this image is not # a desktop, so a real install would fail on runtime libraries that # say nothing about whether the package is well formed. - pacman -Qlp dist/*.pkg.tar.zst | head -20 + # To a file and then head: `| head` would kill pacman with SIGPIPE + # once head has its 20 lines, and these steps run with pipefail. + pacman -Qlp dist/*.pkg.tar.zst > contents.txt + echo "entries: $(wc -l < contents.txt)" + head -20 contents.txt # ---- Debian ------------------------------------------------------- # @@ -364,7 +409,13 @@ jobs: run: | set -eux dpkg-deb --info dist/*.deb - dpkg-deb --contents dist/*.deb | head -20 + # To a file and then head, not `| head`. Actions runs these steps with + # pipefail, and head closing the pipe after 20 lines kills dpkg-deb + # with SIGPIPE, which pipefail reports as a failed step -- a green + # 217 MB package failed here on nothing but that. + dpkg-deb --contents dist/*.deb > contents.txt + echo "entries: $(wc -l < contents.txt)" + head -20 contents.txt # lintian is not installed and would fail this package on a dozen # policy points that do not apply to a desktop fork shipped outside # the archive. What matters here is that dpkg can read it back. diff --git a/packaging/arch/PKGBUILD b/packaging/arch/PKGBUILD index b2679df..a20378c 100644 --- a/packaging/arch/PKGBUILD +++ b/packaging/arch/PKGBUILD @@ -45,16 +45,24 @@ provides=("cosmic-comp=$pkgver" "cosmic-session=$pkgver") options=('!strip' '!debug') package() { - # Set by make-packages.sh. Failing loudly here beats producing an empty - # package, which is what a bare `cp -a "$unset/."` would do. + # Points at a tree `just install` has already staged. Failing loudly here + # beats producing an empty package, which is what a bare `cp -a "$unset/."` + # would do. The workflow sets it; by hand it is + # just install "$PWD/stage" /usr + # HYPRCOSMIC_STAGEDIR="$PWD/stage" makepkg --nodeps if [ -z "$HYPRCOSMIC_STAGEDIR" ] || [ ! -d "$HYPRCOSMIC_STAGEDIR/usr" ]; then - echo "HYPRCOSMIC_STAGEDIR unset or has no usr/; see tools/make-packages.sh" >&2 + echo "HYPRCOSMIC_STAGEDIR unset or has no usr/; see .github/workflows/packages.yml" >&2 return 1 fi cp -a "$HYPRCOSMIC_STAGEDIR/." "$pkgdir/" - # The two files a broken install shows up in first: a bad Exec line puts an - # entry on the greeter's menu that fails silently when it is chosen. - desktop-file-validate "$pkgdir/usr/share/wayland-sessions/hyprcosmic.desktop" - desktop-file-validate "$pkgdir/usr/share/wayland-sessions/cosmic.desktop" + # No desktop-file-validate on the session entries. It rejects DesktopNames, + # the key a display manager reads to set XDG_CURRENT_DESKTOP, because the + # Desktop Entry Specification registers keys for application launchers and + # these are session files. cosmic.desktop here is upstream cosmic-session's, + # unchanged by this fork apart from the Exec path, and the copy Fedora ships + # as cosmic-session-1.5.0-1.fc44 fails the identical check -- so this is the + # validator's gap, not something the fork introduced. The workflow + # checks what actually matters instead -- that Exec names a file this + # package installs -- against the staged tree, before makepkg sees it. } diff --git a/packaging/fedora/hyprcosmic.spec b/packaging/fedora/hyprcosmic.spec index e5b40a8..6905805 100644 --- a/packaging/fedora/hyprcosmic.spec +++ b/packaging/fedora/hyprcosmic.spec @@ -106,11 +106,17 @@ test -n "%{stagedir}" || { echo "define stagedir: see .github/workflows/packages test -d "%{stagedir}/usr" || { echo "%{stagedir}/usr missing; run just install first" >&2; exit 1; } cp -a "%{stagedir}/." "%{buildroot}/" -# The desktop entries are the two files a broken install shows up in first, so -# they are validated rather than assumed. A .desktop with a bad Exec line puts -# an entry on the greeter's menu that fails silently when chosen. -desktop-file-validate "%{buildroot}%{_datadir}/wayland-sessions/hyprcosmic.desktop" -desktop-file-validate "%{buildroot}%{_datadir}/wayland-sessions/cosmic.desktop" +# The session entries are checked by the workflow against the staged tree, not +# with desktop-file-validate here. desktop-file-validate rejects DesktopNames, +# the key a display manager reads to set XDG_CURRENT_DESKTOP, because the +# Desktop Entry Specification registers keys for application launchers and this +# is a session file. cosmic.desktop here is upstream cosmic-session's, unchanged +# by this fork apart from the Exec path, and the copy Fedora already ships as +# cosmic-session-1.5.0-1.fc44 fails the identical check -- so this is the +# validator's gap, not something the fork introduced. Dropping the key would +# satisfy the validator and break the session. +# See "Check the session entries" in .github/workflows/packages.yml, which +# tests what actually matters: that Exec names a file this package installs. # Generated by the workflow from the staged tree rather than written out here. # A hand-maintained list across 27 components would be wrong within a week, and @@ -119,5 +125,5 @@ desktop-file-validate "%{buildroot}%{_datadir}/wayland-sessions/cosmic.desktop" %files -f %{filelist} %changelog -* Sun Aug 10 2026 dingo - 0.1.0-1 +* Mon Aug 10 2026 dingo - 0.1.0-1 - First package of the fork: COSMIC replaced as a unit, HyDE shell, cosmic-conf.