detached 06e1112

feat(packaging): Ubuntu 24.04/26.04 .deb packages (#137)

* chore(packaging): align package descriptions with the README tagline

* feat(packaging): build and smoke-test Ubuntu .deb packages in releases
commit
06e11122322c93077ff103e17fdd8de61f9c5c6e
author
bnema · · 2026-10-05 17:26 UTC
committer
GitHub · · 2026-10-05 17:26 UTC
parent
245c4bb
signature
GPG UnverifiedB5690EEEBB952194 The key is unknown
7 files · +109 -4
M .github/workflows/release.yml +12 -0
@@ -26,6 +26,17 @@ jobs:
2626 - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
2727 with:
2828 go-version-file: go.mod
29+ - uses: goreleaser/goreleaser-action@f06c13b6b1a9625abc9e6e439d9c05a8f2190e94 # v7.2.3
30+ with:
31+ distribution: goreleaser
32+ version: '~> v2'
33+ # Snapshot first: the .deb is installed on Ubuntu before anything ships.
34+ args: release --snapshot --clean --skip=aur
35+ - name: Smoke-test the .deb on Ubuntu LTS
36+ run: |
37+ for v in 24.04 26.04; do
38+ packaging/deb/smoke-test.sh "$v" dist/neferwl_*_amd64.deb
39+ done
2940 - uses: goreleaser/goreleaser-action@f06c13b6b1a9625abc9e6e439d9c05a8f2190e94 # v7.2.3
3041 with:
3142 distribution: goreleaser
@@ -37,6 +48,7 @@ jobs:
3748 with:
3849 subject-path: |
3950 dist/*.tar.gz
51+ dist/*.deb
4052 dist/checksums.txt
4153 - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
4254 with:
@@ -26,6 +26,17 @@ jobs:
26 - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.026 - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
27 with:27 with:
28 go-version-file: go.mod28 go-version-file: go.mod
29+ - uses: goreleaser/goreleaser-action@f06c13b6b1a9625abc9e6e439d9c05a8f2190e94 # v7.2.3
30+ with:
31+ distribution: goreleaser
32+ version: '~> v2'
33+ # Snapshot first: the .deb is installed on Ubuntu before anything ships.
34+ args: release --snapshot --clean --skip=aur
35+ - name: Smoke-test the .deb on Ubuntu LTS
36+ run: |
37+ for v in 24.04 26.04; do
38+ packaging/deb/smoke-test.sh "$v" dist/neferwl_*_amd64.deb
39+ done
29 - uses: goreleaser/goreleaser-action@f06c13b6b1a9625abc9e6e439d9c05a8f2190e94 # v7.2.340 - uses: goreleaser/goreleaser-action@f06c13b6b1a9625abc9e6e439d9c05a8f2190e94 # v7.2.3
30 with:41 with:
31 distribution: goreleaser42 distribution: goreleaser
@@ -37,6 +48,7 @@ jobs:
37 with:48 with:
38 subject-path: |49 subject-path: |
39 dist/*.tar.gz50 dist/*.tar.gz
51+ dist/*.deb
40 dist/checksums.txt52 dist/checksums.txt
41 - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.153 - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
42 with:54 with:
M .goreleaser.yaml +64 -1
@@ -42,6 +42,59 @@ archives:
4242 - packaging/neferwl.desktop
4343 - packaging/neferwl-portals.conf
4444
45+nfpms:
46+ - id: neferwl
47+ ids: [neferwl]
48+ package_name: neferwl
49+ file_name_template: "{{ .PackageName }}_{{ .Version }}_{{ .Arch }}"
50+ formats: [deb]
51+ vendor: bnema
52+ homepage: https://github.com/bnema/neferwl
53+ maintainer: "bnema <b@bnema.dev>"
54+ description: A Wayland compositor that spends its frames on your apps, not on itself
55+ license: GPL-3.0-only
56+ section: x11
57+ bindir: /usr/bin
58+ # Loaded at runtime (purego, no cgo): dpkg-shlibdeps cannot see them.
59+ dependencies:
60+ - libc6
61+ - libinput10
62+ - libseat1
63+ - libudev1
64+ - libxkbcommon0
65+ - libvulkan1
66+ - mesa-vulkan-drivers | vulkan-icd
67+ - dbus
68+ - libcap2-bin
69+ suggests:
70+ - xwayland-satellite
71+ - foot
72+ - fuzzel
73+ - xdg-desktop-portal-gtk
74+ - xdg-desktop-portal-wlr
75+ scripts:
76+ postinstall: packaging/deb/postinst
77+ contents:
78+ - src: packaging/neferwl-session
79+ dst: /usr/bin/neferwl-session
80+ file_info: {mode: 0755}
81+ - src: packaging/neferwl.service
82+ dst: /usr/lib/systemd/user/neferwl.service
83+ - src: packaging/neferwl-shutdown.target
84+ dst: /usr/lib/systemd/user/neferwl-shutdown.target
85+ - src: packaging/neferwl.desktop
86+ dst: /usr/share/wayland-sessions/neferwl.desktop
87+ - src: packaging/neferwl-portals.conf
88+ dst: /usr/share/xdg-desktop-portal/neferwl-portals.conf
89+ - src: examples/config
90+ dst: /usr/share/doc/neferwl/config.example
91+ - src: examples/capture-allow
92+ dst: /usr/share/doc/neferwl/capture-allow.example
93+ - src: README.md
94+ dst: /usr/share/doc/neferwl/README.md
95+ - src: LICENSE
96+ dst: /usr/share/doc/neferwl/copyright
97+
4598 checksum:
4699 name_template: checksums.txt
47100 algorithm: sha256
@@ -108,6 +161,16 @@ release:
108161 gh attestation verify neferwl_{{ .Version }}_linux_amd64.tar.gz -R bnema/neferwl
109162 ```
110163
164+ ### Install on Ubuntu 24.04 and 26.04
165+
166+ Replace `amd64` with `arm64` on ARM.
167+
168+ ```sh
169+ gh release download {{ .Tag }} -R bnema/neferwl -p 'neferwl_{{ .Version }}_amd64.deb' -p checksums.txt
170+ sha256sum -c --ignore-missing checksums.txt
171+ sudo apt install ./neferwl_{{ .Version }}_amd64.deb
172+ ```
173+
111174 The archive holds the `neferwl` binary, the session files from `packaging/` and `examples/config`. See the [README](https://github.com/bnema/neferwl#readme) for runtime dependencies and the session setup.
112175 footer: |
113176 ---
@@ -118,7 +181,7 @@ aurs:
118181 - name: neferwl-bin
119182 ids: [neferwl]
120183 homepage: https://github.com/bnema/neferwl
121- description: Minimal Wayland compositor with column tiling, for the TTY
184+ description: A Wayland compositor that spends its frames on your apps, not on itself
122185 maintainers:
123186 - "bnema <b at bnema dot dev>"
124187 license: GPL-3.0-only
@@ -42,6 +42,59 @@ archives:
42 - packaging/neferwl.desktop42 - packaging/neferwl.desktop
43 - packaging/neferwl-portals.conf43 - packaging/neferwl-portals.conf
44 44
45+nfpms:
46+ - id: neferwl
47+ ids: [neferwl]
48+ package_name: neferwl
49+ file_name_template: "{{ .PackageName }}_{{ .Version }}_{{ .Arch }}"
50+ formats: [deb]
51+ vendor: bnema
52+ homepage: https://github.com/bnema/neferwl
53+ maintainer: "bnema <b@bnema.dev>"
54+ description: A Wayland compositor that spends its frames on your apps, not on itself
55+ license: GPL-3.0-only
56+ section: x11
57+ bindir: /usr/bin
58+ # Loaded at runtime (purego, no cgo): dpkg-shlibdeps cannot see them.
59+ dependencies:
60+ - libc6
61+ - libinput10
62+ - libseat1
63+ - libudev1
64+ - libxkbcommon0
65+ - libvulkan1
66+ - mesa-vulkan-drivers | vulkan-icd
67+ - dbus
68+ - libcap2-bin
69+ suggests:
70+ - xwayland-satellite
71+ - foot
72+ - fuzzel
73+ - xdg-desktop-portal-gtk
74+ - xdg-desktop-portal-wlr
75+ scripts:
76+ postinstall: packaging/deb/postinst
77+ contents:
78+ - src: packaging/neferwl-session
79+ dst: /usr/bin/neferwl-session
80+ file_info: {mode: 0755}
81+ - src: packaging/neferwl.service
82+ dst: /usr/lib/systemd/user/neferwl.service
83+ - src: packaging/neferwl-shutdown.target
84+ dst: /usr/lib/systemd/user/neferwl-shutdown.target
85+ - src: packaging/neferwl.desktop
86+ dst: /usr/share/wayland-sessions/neferwl.desktop
87+ - src: packaging/neferwl-portals.conf
88+ dst: /usr/share/xdg-desktop-portal/neferwl-portals.conf
89+ - src: examples/config
90+ dst: /usr/share/doc/neferwl/config.example
91+ - src: examples/capture-allow
92+ dst: /usr/share/doc/neferwl/capture-allow.example
93+ - src: README.md
94+ dst: /usr/share/doc/neferwl/README.md
95+ - src: LICENSE
96+ dst: /usr/share/doc/neferwl/copyright
97+
45 checksum:98 checksum:
46 name_template: checksums.txt99 name_template: checksums.txt
47 algorithm: sha256100 algorithm: sha256
@@ -108,6 +161,16 @@ release:
108 gh attestation verify neferwl_{{ .Version }}_linux_amd64.tar.gz -R bnema/neferwl161 gh attestation verify neferwl_{{ .Version }}_linux_amd64.tar.gz -R bnema/neferwl
109 ```162 ```
110 163
164+ ### Install on Ubuntu 24.04 and 26.04
165+
166+ Replace `amd64` with `arm64` on ARM.
167+
168+ ```sh
169+ gh release download {{ .Tag }} -R bnema/neferwl -p 'neferwl_{{ .Version }}_amd64.deb' -p checksums.txt
170+ sha256sum -c --ignore-missing checksums.txt
171+ sudo apt install ./neferwl_{{ .Version }}_amd64.deb
172+ ```
173+
111 The archive holds the `neferwl` binary, the session files from `packaging/` and `examples/config`. See the [README](https://github.com/bnema/neferwl#readme) for runtime dependencies and the session setup.174 The archive holds the `neferwl` binary, the session files from `packaging/` and `examples/config`. See the [README](https://github.com/bnema/neferwl#readme) for runtime dependencies and the session setup.
112 footer: |175 footer: |
113 ---176 ---
@@ -118,7 +181,7 @@ aurs:
118 - name: neferwl-bin181 - name: neferwl-bin
119 ids: [neferwl]182 ids: [neferwl]
120 homepage: https://github.com/bnema/neferwl183 homepage: https://github.com/bnema/neferwl
121- description: Minimal Wayland compositor with column tiling, for the TTY184+ description: A Wayland compositor that spends its frames on your apps, not on itself
122 maintainers:185 maintainers:
123 - "bnema <b at bnema dot dev>"186 - "bnema <b at bnema dot dev>"
124 license: GPL-3.0-only187 license: GPL-3.0-only
M packaging/arch/PKGBUILD +1 -1
@@ -2,7 +2,7 @@
22 pkgname=neferwl
33 pkgver=0.0.0
44 pkgrel=1
5-pkgdesc='Minimal Wayland compositor with column tiling, for the TTY'
5+pkgdesc='A Wayland compositor that spends its frames on your apps, not on itself'
66 arch=('x86_64')
77 url='https://github.com/bnema/neferwl'
88 license=('GPL-3.0-only')
@@ -2,7 +2,7 @@
2 pkgname=neferwl2 pkgname=neferwl
3 pkgver=0.0.03 pkgver=0.0.0
4 pkgrel=14 pkgrel=1
5-pkgdesc='Minimal Wayland compositor with column tiling, for the TTY'5+pkgdesc='A Wayland compositor that spends its frames on your apps, not on itself'
6 arch=('x86_64')6 arch=('x86_64')
7 url='https://github.com/bnema/neferwl'7 url='https://github.com/bnema/neferwl'
8 license=('GPL-3.0-only')8 license=('GPL-3.0-only')
M packaging/aur/neferwl-git/PKGBUILD +1 -1
@@ -4,7 +4,7 @@
44 pkgname=neferwl-git
55 pkgver=0.1.0.r78.ge0b15ca
66 pkgrel=1
7-pkgdesc='Minimal Wayland compositor with column tiling, for the TTY (git version)'
7+pkgdesc='A Wayland compositor that spends its frames on your apps, not on itself (git version)'
88 arch=('x86_64' 'aarch64')
99 url='https://github.com/bnema/neferwl'
1010 license=('GPL-3.0-only')
@@ -4,7 +4,7 @@
4 pkgname=neferwl-git4 pkgname=neferwl-git
5 pkgver=0.1.0.r78.ge0b15ca5 pkgver=0.1.0.r78.ge0b15ca
6 pkgrel=16 pkgrel=1
7-pkgdesc='Minimal Wayland compositor with column tiling, for the TTY (git version)'7+pkgdesc='A Wayland compositor that spends its frames on your apps, not on itself (git version)'
8 arch=('x86_64' 'aarch64')8 arch=('x86_64' 'aarch64')
9 url='https://github.com/bnema/neferwl'9 url='https://github.com/bnema/neferwl'
10 license=('GPL-3.0-only')10 license=('GPL-3.0-only')
A packaging/deb/postinst +8 -0
@@ -0,0 +1,8 @@
1+#!/bin/sh
2+# Real-time input and output threads and the high-priority Vulkan queue need
3+# CAP_SYS_NICE. Apps launched by NeferWL do not inherit it.
4+set -e
5+
6+if [ "$1" = configure ]; then
7+ setcap cap_sys_nice=ep /usr/bin/neferwl || echo 'neferwl: setcap failed, real-time scheduling is off'
8+fi
@@ -0,0 +1,8 @@
1+#!/bin/sh
2+# Real-time input and output threads and the high-priority Vulkan queue need
3+# CAP_SYS_NICE. Apps launched by NeferWL do not inherit it.
4+set -e
5+
6+if [ "$1" = configure ]; then
7+ setcap cap_sys_nice=ep /usr/bin/neferwl || echo 'neferwl: setcap failed, real-time scheduling is off'
8+fi
A packaging/deb/smoke-test.sh +22 -0
@@ -0,0 +1,22 @@
1+#!/bin/sh
2+# Installs a neferwl .deb in a clean Ubuntu container and checks that it runs.
3+# Usage: packaging/deb/smoke-test.sh <ubuntu-version> <path/to/neferwl.deb>
4+# Needs CAP_SYS_NICE in the container: postinst sets it as a file capability.
5+set -eu
6+
7+version=$1
8+deb=$(realpath "$2")
9+
10+docker run --rm --cap-add SYS_NICE -v "$deb:/tmp/neferwl.deb:ro" "ubuntu:$version" sh -euc '
11+ # Ubuntu images skip /usr/share/doc; the example config lives there.
12+ rm -f /etc/dpkg/dpkg.cfg.d/excludes
13+ apt-get update -qq
14+ DEBIAN_FRONTEND=noninteractive apt-get install -y -qq /tmp/neferwl.deb >/dev/null
15+ getcap /usr/bin/neferwl | grep -q cap_sys_nice
16+ neferwl version
17+ neferwl validate-config /usr/share/doc/neferwl/config.example
18+ for lib in libinput.so.10 libseat.so.1 libudev.so.1 libxkbcommon.so.0 libvulkan.so.1; do
19+ ldconfig -p | grep -q "$lib" || { echo "missing $lib"; exit 1; }
20+ done
21+ apt-get remove -y -qq neferwl >/dev/null
22+'
@@ -0,0 +1,22 @@
1+#!/bin/sh
2+# Installs a neferwl .deb in a clean Ubuntu container and checks that it runs.
3+# Usage: packaging/deb/smoke-test.sh <ubuntu-version> <path/to/neferwl.deb>
4+# Needs CAP_SYS_NICE in the container: postinst sets it as a file capability.
5+set -eu
6+
7+version=$1
8+deb=$(realpath "$2")
9+
10+docker run --rm --cap-add SYS_NICE -v "$deb:/tmp/neferwl.deb:ro" "ubuntu:$version" sh -euc '
11+ # Ubuntu images skip /usr/share/doc; the example config lives there.
12+ rm -f /etc/dpkg/dpkg.cfg.d/excludes
13+ apt-get update -qq
14+ DEBIAN_FRONTEND=noninteractive apt-get install -y -qq /tmp/neferwl.deb >/dev/null
15+ getcap /usr/bin/neferwl | grep -q cap_sys_nice
16+ neferwl version
17+ neferwl validate-config /usr/share/doc/neferwl/config.example
18+ for lib in libinput.so.10 libseat.so.1 libudev.so.1 libxkbcommon.so.0 libvulkan.so.1; do
19+ ldconfig -p | grep -q "$lib" || { echo "missing $lib"; exit 1; }
20+ done
21+ apt-get remove -y -qq neferwl >/dev/null
22+'
M packaging/neferwl.desktop +1 -1
@@ -1,6 +1,6 @@
11 [Desktop Entry]
22 Name=NeferWL
3-Comment=Minimal Wayland compositor with column tiling
3+Comment=A Wayland compositor that spends its frames on your apps, not on itself
44 Exec=neferwl-session
55 Type=Application
66 DesktopNames=neferwl
@@ -1,6 +1,6 @@
1 [Desktop Entry]1 [Desktop Entry]
2 Name=NeferWL2 Name=NeferWL
3-Comment=Minimal Wayland compositor with column tiling3+Comment=A Wayland compositor that spends its frames on your apps, not on itself
4 Exec=neferwl-session4 Exec=neferwl-session
5 Type=Application5 Type=Application
6 DesktopNames=neferwl6 DesktopNames=neferwl

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 24

Tags 10

↑↓ moveenter openesc close