Skip to content

Commit 4062d69

Browse files
committed
Ship the tool as a .deb, an .rpm and a pacman package
A tarball has to be upgraded by hand and nothing on the machine knows it is there. Every release now also carries three package formats for both architectures, so the tool is installed and upgraded the way everything else on the system is. The nfpms block puts the binary in /usr/bin, because the package manager owns it, and README, LICENSE and the example config under /usr/share/doc. It provides the command name and conflicts with anything else shipping it, so a second copy is a conflict rather than a silent overwrite. GoReleaser cannot read tool.json, so the package description is a copy of the tagline. `make manifest` now also runs the kit's check-nfpm.py, which fails when the two disagree, and CI runs it on every push. `install.repo_url` points at the family package repository, which is what the README's one-time setup is derived from: the one-liner, and next to it the commands it stands for. The release job tells tui-tools/pkgs that new packages exist, so the repository rebuilds on release rather than on its weekly run; the step is inert until PKGS_DISPATCH_TOKEN is set.
1 parent a2f36e0 commit 4062d69

7 files changed

Lines changed: 165 additions & 12 deletions

File tree

‎.github/workflows/ci.yml‎

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,23 @@ jobs:
129129
--spec=draft2020 -c ajv-formats \
130130
-s /tmp/tool.schema.json -d tool.json
131131
132+
# GoReleaser cannot read tool.json, so the package description in
133+
# .goreleaser.yaml is a copy of the manifest's tagline. This is what
134+
# stops the copy from drifting, and it checks the rest of the package
135+
# metadata the family fixed by convention along with it.
136+
- uses: actions/setup-go@v7
137+
with:
138+
go-version-file: go.mod
139+
check-latest: true
140+
141+
- name: package metadata matches the manifest
142+
run: |
143+
python3 -m pip install --quiet --disable-pip-version-check pyyaml
144+
go mod download github.com/tui-tools/tui-kit
145+
kit=$(go list -m -f '{{.Dir}}' github.com/tui-tools/tui-kit)
146+
python3 "$kit/tools/check-nfpm.py" --manifest tool.json \
147+
--config .goreleaser.yaml
148+
132149
release:
133150
name: release
134151
if: startsWith(github.ref, 'refs/tags/v')
@@ -138,6 +155,10 @@ jobs:
138155
contents: write
139156
env:
140157
SITE_DISPATCH_TOKEN: ${{ secrets.SITE_DISPATCH_TOKEN }}
158+
# The package repository builder. PKGS_DISPATCH_TOKEN is the one to
159+
# set; SITE_DISPATCH_TOKEN is accepted as a fallback so a single
160+
# organization token can drive both rebuilds.
161+
PKGS_DISPATCH_TOKEN: ${{ secrets.PKGS_DISPATCH_TOKEN || secrets.SITE_DISPATCH_TOKEN }}
141162
steps:
142163
- uses: actions/checkout@v7
143164
with:
@@ -169,3 +190,17 @@ jobs:
169190
gh api repos/tui-tools/tui-tools.github.io/dispatches \
170191
-f event_type=tool-released \
171192
-f 'client_payload[tool]=tui-firewall'
193+
194+
# Tell the package repository builder that new .deb/.rpm/pacman files
195+
# exist, so pkgs.tui.tools picks them up now rather than on its weekly
196+
# run. Inert until PKGS_DISPATCH_TOKEN exists: a fine-grained PAT with
197+
# "Contents: read and write" on tui-tools/pkgs.
198+
- name: notify the package repository
199+
if: env.PKGS_DISPATCH_TOKEN != ''
200+
env:
201+
GH_TOKEN: ${{ env.PKGS_DISPATCH_TOKEN }}
202+
run: |
203+
gh api repos/tui-tools/pkgs/dispatches \
204+
-f event_type=tool-released \
205+
-f 'client_payload[tool]=tui-firewall' \
206+
-f "client_payload[version]=${GITHUB_REF_NAME#v}"

‎.goreleaser.yaml‎

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,57 @@ archives:
4545
- README.md
4646
- examples/config.toml
4747

48+
# The distribution packages. Three formats times two architectures is six
49+
# files per release, and they are what pkgs.tui.tools indexes into the apt,
50+
# dnf and pacman repositories: a tool is then installed and upgraded the way
51+
# everything else on the machine is.
52+
#
53+
# GoReleaser cannot read tool.json, so `description` below is a copy of the
54+
# manifest's tagline. tui-kit/tools/check-nfpm.py asserts the two are
55+
# identical, and `make manifest` runs it, so the copy cannot drift.
56+
nfpms:
57+
- id: tui-firewall
58+
ids:
59+
- tui-firewall
60+
package_name: tui-firewall
61+
formats:
62+
- deb
63+
- rpm
64+
- archlinux
65+
# Each ecosystem's own naming, so the files look native where they land:
66+
# tui-firewall_0.1.0_amd64.deb, tui-firewall-0.1.0.x86_64.rpm,
67+
# tui-firewall-0.1.0-1-x86_64.pkg.tar.zst.
68+
file_name_template: "{{ .ConventionalFileName }}"
69+
vendor: tui-tools
70+
homepage: https://tui.tools/tools/tui-firewall/
71+
maintainer: tui-tools <maintainers@tui.tools>
72+
description: "ufw and firewalld, with every change previewed before it runs"
73+
license: MIT
74+
# The binary belongs in the distribution's own path, not /usr/local: it
75+
# arrives through the package manager, so the package manager owns it.
76+
bindir: /usr/bin
77+
section: utils
78+
priority: optional
79+
contents:
80+
- src: README.md
81+
dst: /usr/share/doc/tui-firewall/README.md
82+
- src: LICENSE
83+
dst: /usr/share/doc/tui-firewall/LICENSE
84+
- src: examples/config.toml
85+
dst: /usr/share/doc/tui-firewall/config.toml
86+
# The package owns the binary name, so anything else shipping the same
87+
# command — an AUR -bin build, a hand-rolled local package — is a
88+
# conflict rather than a silent overwrite.
89+
provides:
90+
- tui-firewall
91+
conflicts:
92+
- tui-firewall-bin
93+
rpm:
94+
group: Applications/System
95+
archlinux:
96+
pkgbase: tui-firewall
97+
packager: tui-tools <maintainers@tui.tools>
98+
4899
checksum:
49100
name_template: checksums.txt
50101

‎Makefile‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ manifest:
9898
@npx --yes -p ajv-cli@5 -p ajv-formats@3 ajv validate \
9999
--spec=draft2020 -c ajv-formats \
100100
-s /tmp/tui-tool.schema.json -d tool.json
101+
@python3 $(KIT)/tools/check-nfpm.py --manifest tool.json \
102+
--config .goreleaser.yaml
101103

102104
## clean: remove build output.
103105
clean:

‎README.md‎

Lines changed: 69 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ firewalld.
2626
### Any distribution, static binary
2727

2828
```sh
29-
curl -fsSL https://github.com/tui-tools/tui-firewall/releases/download/v0.1.0/tui-firewall_0.1.0_linux_amd64.tar.gz | tar -xz tui-firewall
29+
curl -fsSL https://github.com/tui-tools/tui-firewall/releases/download/v0.2.0/tui-firewall_0.2.0_linux_amd64.tar.gz | tar -xz tui-firewall
3030
sudo install -m0755 tui-firewall /usr/local/bin/tui-firewall
3131
```
3232

@@ -51,11 +51,34 @@ turns them on.
5151
Needs the tui-tools repository, which is a [one-time
5252
setup](https://tui-tools.github.io/install/).
5353

54+
The one-liner detects the distribution and adds the repository and its signing
55+
key:
56+
57+
```sh
58+
curl -fsSL https://pkgs.tui.tools/install.sh | sh
59+
```
60+
61+
Piping a script into a shell is not this family's style, so here is the same
62+
setup by hand — read it, or read the script first with `curl -fsSL
63+
https://pkgs.tui.tools/install.sh -o install.sh`:
64+
65+
```sh
66+
curl -fsSL -o /tmp/tui-tools.asc https://pkgs.tui.tools/pubkey.asc
67+
sudo pacman-key --add /tmp/tui-tools.asc
68+
sudo pacman-key --lsign-key \
69+
"$(gpg --show-keys --with-colons /tmp/tui-tools.asc | awk -F: '/^fpr:/{print $10; exit}')"
70+
printf '[tui-tools]\nServer = https://pkgs.tui.tools/arch/$arch\n' \
71+
| sudo tee -a /etc/pacman.conf
72+
sudo pacman -Sy
73+
```
74+
75+
Then, and for every other tool in the family:
76+
5477
```sh
5578
sudo pacman -S tui-firewall
5679
```
5780

58-
Add the tui-tools repository to pacman.conf first.
81+
Upgrades then arrive with the rest of your system updates.
5982

6083
### Arch Linux (AUR) — coming soon
6184

@@ -70,22 +93,63 @@ The -bin package installs the released static binary.
7093
Needs the tui-tools repository, which is a [one-time
7194
setup](https://tui-tools.github.io/install/).
7295

96+
The one-liner detects the distribution and adds the repository and its signing
97+
key:
98+
99+
```sh
100+
curl -fsSL https://pkgs.tui.tools/install.sh | sh
101+
```
102+
103+
Piping a script into a shell is not this family's style, so here is the same
104+
setup by hand — read it, or read the script first with `curl -fsSL
105+
https://pkgs.tui.tools/install.sh -o install.sh`:
106+
107+
```sh
108+
sudo install -d -m 0755 /etc/apt/keyrings
109+
curl -fsSL https://pkgs.tui.tools/pubkey.asc \
110+
| sudo gpg --dearmor -o /etc/apt/keyrings/tui-tools.gpg
111+
echo "deb [signed-by=/etc/apt/keyrings/tui-tools.gpg] https://pkgs.tui.tools/deb stable main" \
112+
| sudo tee /etc/apt/sources.list.d/tui-tools.list
113+
sudo apt update
114+
```
115+
116+
Then, and for every other tool in the family:
117+
73118
```sh
74119
sudo apt install tui-firewall
75120
```
76121

77-
Add the tui-tools apt repository and its keyring first.
122+
Upgrades then arrive with the rest of your system updates.
78123

79124
### Fedora and RHEL — coming soon
80125

81126
Needs the tui-tools repository, which is a [one-time
82127
setup](https://tui-tools.github.io/install/).
83128

129+
The one-liner detects the distribution and adds the repository and its signing
130+
key:
131+
132+
```sh
133+
curl -fsSL https://pkgs.tui.tools/install.sh | sh
134+
```
135+
136+
Piping a script into a shell is not this family's style, so here is the same
137+
setup by hand — read it, or read the script first with `curl -fsSL
138+
https://pkgs.tui.tools/install.sh -o install.sh`:
139+
140+
```sh
141+
sudo rpm --import https://pkgs.tui.tools/pubkey.asc
142+
sudo curl -fsSL -o /etc/yum.repos.d/tui-tools.repo https://pkgs.tui.tools/rpm/tui-tools.repo
143+
sudo dnf makecache
144+
```
145+
146+
Then, and for every other tool in the family:
147+
84148
```sh
85149
sudo dnf install tui-firewall
86150
```
87151

88-
Add the tui-tools.repo file first.
152+
Upgrades then arrive with the rest of your system updates.
89153

90154
### openSUSE — coming soon
91155

@@ -96,7 +160,7 @@ setup](https://tui-tools.github.io/install/).
96160
sudo zypper install tui-firewall
97161
```
98162

99-
Add the tui-tools repository first.
163+
The rpm repository is shared with dnf; zypper support is not tested yet.
100164

101165
### Verify a download
102166

‎go.mod‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ require (
66
github.com/charmbracelet/bubbles v1.0.0
77
github.com/charmbracelet/bubbletea v1.3.10
88
github.com/charmbracelet/lipgloss v1.1.0
9-
github.com/tui-tools/tui-kit v0.2.3
9+
github.com/tui-tools/tui-kit v0.2.4
1010
)
1111

1212
require (

‎go.sum‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc
3838
github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk=
3939
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
4040
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
41-
github.com/tui-tools/tui-kit v0.2.3 h1:wzL2AdfAvO2Bdk/k7OrvG48NwgxFqYXHX9yYDTZWHv0=
42-
github.com/tui-tools/tui-kit v0.2.3/go.mod h1:Vpg1NcQ5ktylMvXTzsixdHjLUNxhntR3ZYSOYaQ7/FQ=
41+
github.com/tui-tools/tui-kit v0.2.4 h1:/d2mdFSO0yMwPeV8LVjbOxZ6nBAkVryzXO/CHN25umw=
42+
github.com/tui-tools/tui-kit v0.2.4/go.mod h1:Vpg1NcQ5ktylMvXTzsixdHjLUNxhntR3ZYSOYaQ7/FQ=
4343
github.com/xo/terminfo v1.0.0 h1:2ZpYzqWzyyytjk3TP6aJVDhkMAkc99/1xKQdA3TDTBY=
4444
github.com/xo/terminfo v1.0.0/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
4545
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=

‎tool.json‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -156,14 +156,15 @@
156156
}
157157
],
158158
"install": {
159+
"repo_url": "https://pkgs.tui.tools",
159160
"pacman": {
160161
"available": false,
161162
"package": "tui-firewall",
162163
"repo": "tui-tools",
163164
"requires_repo_setup": true,
164165
"command": "sudo pacman -S tui-firewall",
165166
"url": "https://pkgs.tui.tools/arch",
166-
"note": "Add the tui-tools repository to pacman.conf first."
167+
"note": "Upgrades then arrive with the rest of your system updates."
167168
},
168169
"aur": {
169170
"available": false,
@@ -180,7 +181,7 @@
180181
"requires_repo_setup": true,
181182
"command": "sudo apt install tui-firewall",
182183
"url": "https://pkgs.tui.tools/deb",
183-
"note": "Add the tui-tools apt repository and its keyring first."
184+
"note": "Upgrades then arrive with the rest of your system updates."
184185
},
185186
"dnf": {
186187
"available": false,
@@ -189,7 +190,7 @@
189190
"requires_repo_setup": true,
190191
"command": "sudo dnf install tui-firewall",
191192
"url": "https://pkgs.tui.tools/rpm",
192-
"note": "Add the tui-tools.repo file first."
193+
"note": "Upgrades then arrive with the rest of your system updates."
193194
},
194195
"zypper": {
195196
"available": false,
@@ -198,7 +199,7 @@
198199
"requires_repo_setup": true,
199200
"command": "sudo zypper install tui-firewall",
200201
"url": "https://pkgs.tui.tools/rpm",
201-
"note": "Add the tui-tools repository first."
202+
"note": "The rpm repository is shared with dnf; zypper support is not tested yet."
202203
},
203204
"binary": {
204205
"available": true,

0 commit comments

Comments
 (0)