diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index dde21ad..c72026d 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -40,6 +40,18 @@ on:
# latest.json, and skip the APT/DNF repos; stable clients and repos never
# see them.
#
+# Alongside each versioned artifact, every package job stages a second copy
+# under a version-less STABLE NAME:
+#
+# dish-amd64.deb dish-x86_64.rpm Dish-x86_64.AppImage Dish-x86_64.flatpak
+#
+# Those names are a permanent API, like dish-windows' dish-setup.exe and
+# latest.json: releases/latest/download/ always resolves to the newest
+# published build, so download pages can link "the latest build" without
+# being rebuilt per release. Renaming or dropping one silently breaks every
+# consumer of that permalink. The stable copies flow through the same harden
+# job, so SHA256SUMS and the cosign signatures cover them too.
+#
# Linux binaries are not signed with a platform key by default; the
# `required-secrets` gate therefore enforces only that the cosign keyless
# flow is reachable (id-token: write).
@@ -276,6 +288,12 @@ jobs:
fi
echo "::notice::dish came up, shut down on SIGTERM and exited 0"
+ # Stable-name copy for the /releases/latest/download/ permalink; the
+ # dash (vs the versioned name's underscores) keeps it clear of the
+ # dish_*_amd64.deb glob.
+ - name: Stage stable-name alias
+ run: cp dist/dish_*_amd64.deb dist/dish-amd64.deb
+
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: linux-deb
@@ -408,6 +426,10 @@ jobs:
fi
echo "::notice::dish came up, shut down on SIGTERM and exited 0"
+ # Stable-name copy for the /releases/latest/download/ permalink.
+ - name: Stage stable-name alias
+ run: cp dist/dish-*.x86_64.rpm dist/dish-x86_64.rpm
+
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: linux-rpm
@@ -492,6 +514,12 @@ jobs:
- name: Build AppImage
run: scripts/build-appimage.sh
+ # Stable-name copy for the /releases/latest/download/ permalink.
+ # No .zsync/.sha256 alias: AppImageUpdate matches the versioned
+ # pattern, and SHA256SUMS covers the alias.
+ - name: Stage stable-name alias
+ run: cp dist/Dish-*-x86_64.AppImage dist/Dish-x86_64.AppImage
+
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: linux-appimage
@@ -549,6 +577,9 @@ jobs:
flatpak build-bundle build-flatpak/repo \
"dist/Dish-${{ steps.ver.outputs.version }}-x86_64.flatpak" \
com.tinkernorth.Dish
+ # Stable-name copy for the /releases/latest/download/ permalink.
+ cp "dist/Dish-${{ steps.ver.outputs.version }}-x86_64.flatpak" \
+ dist/Dish-x86_64.flatpak
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index daf36ab..274d530 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -18,6 +18,18 @@ the repos share a version number.
## [Unreleased]
+## [0.2.0] - 2026-08-24
+
+### Added
+
+- Every release now also uploads its packages under version-less stable
+ names: `dish-amd64.deb`, `dish-x86_64.rpm`, `Dish-x86_64.AppImage` and
+ `Dish-x86_64.flatpak`. `releases/latest/download/` is therefore a
+ permanent link to the newest build, alongside `latest.json` which already
+ worked that way. The stable names are covered by SHA256SUMS and the cosign
+ signatures, and they are a public API: download pages link them, so they
+ must not be renamed or dropped.
+
## [0.1.2] - 2026-08-24
### Fixed
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5283bc9..a7a8370 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.21)
project(Dish
- VERSION 0.1.2
+ VERSION 0.2.0
DESCRIPTION "Dish Linux client for the Satellite gamepad-over-LAN protocol"
LANGUAGES CXX)
diff --git a/packaging/com.tinkernorth.Dish.metainfo.xml b/packaging/com.tinkernorth.Dish.metainfo.xml
index 9d95179..04ad698 100644
--- a/packaging/com.tinkernorth.Dish.metainfo.xml
+++ b/packaging/com.tinkernorth.Dish.metainfo.xml
@@ -102,6 +102,12 @@
+
+ https://github.com/TinkerNorth/dish-linux/releases/tag/0.2.0
+
+ Adds version-less stable download names for every package, so the newest build is always available at the same link. No changes to the client itself.
+
+
https://github.com/TinkerNorth/dish-linux/releases/tag/0.1.2
diff --git a/packaging/repo/index.html b/packaging/repo/index.html
index ca1cce9..2b34def 100644
--- a/packaging/repo/index.html
+++ b/packaging/repo/index.html
@@ -125,9 +125,10 @@ Arch Linux
Ubuntu LTS, older distros, no package manager
Every release ships a
portable AppImage (self-updating via AppImageUpdate/zsync) and a Flatpak
- bundle:
- chmod +x Dish-X.Y.Z-x86_64.AppImage
-./Dish-X.Y.Z-x86_64.AppImage
+ bundle. The newest build is always at the same link:
+ curl -fLO https://github.com/TinkerNorth/dish-linux/releases/latest/download/Dish-x86_64.AppImage
+chmod +x Dish-x86_64.AppImage
+./Dish-x86_64.AppImage
USB-direct claiming needs a udev rule no AppImage or Flatpak can install;
without it Dish keeps the pad streaming on the SDL path, just rate-capped.
The app shows the one-time fix when it applies, and