Give beta DEB and RPM packages a pre-release number (#113) (#116)

* build: give beta DEB and RPM packages a pre-release number (#113)

composePackageVersion is the package version of every Compose target
format, so an RPM or DEB built from a beta tag carried exactly the
version of the following stable one. dnf, rpm -U and dpkg refuse to
replace a package by one of equal version, so a beta user could not
move to the stable.

Keep the version and tell the packages apart by the package release
number, following the Fedora pre-release convention: the new Gradle
property linuxAppRelease is passed to jpackage as --linux-app-release
(Compose LinuxPlatformSettings.appRelease) and defaults to 1.

  beta-v1.50.0-beta-001 -> 1.50.0-0.beta.001
  beta-v1.50.0-rc02     -> 1.50.0-0.rc02
  v1.50.0               -> 1.50.0-1

Everything starting with "0." sorts below "1" for both rpm and dpkg.
Nightlies and local builds do not set the property and keep release 1.

Fixes #113

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* ci: derive the Linux release number from the tag and verify the tag version (#113)

The DEB and RPM jobs now compute the package release from the tag
before calling Gradle and pass it as -PlinuxAppRelease: a stable
vX.Y.Z tag gives 1, a beta-vX.Y.Z-<suffix> tag gives 0.<suffix> with
"-" turned into ".". The result must match [A-Za-z0-9.]+, otherwise
the step fails. A workflow_dispatch run from a branch keeps release 1
like the nightlies; nightly-artifacts.yml is unchanged.

The test job, which every packaging job depends on, now checks right
after the checkout that the X.Y.Z in the tag equals
composePackageVersion in gradle.properties and fails with a clear
message otherwise, so a mistagged commit fails before an hour of
packaging rather than shipping packages whose version contradicts
their file name and upgrade order.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* docs: describe the pre-release number of beta DEB and RPM packages (#113)

The German and English installation manuals say in the Debian/Ubuntu
and Fedora sections that beta packages carry a pre-release number
below the stable one, so the stable installs as an upgrade over a
beta. The v1.50 changelogs gain the matching "Fixed" entry, and
PROJECT_CONTEXT.md records the rule next to the MSI decision.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Rsclub2_2andClaude Fable 5.1 authored and GitHub committed 2026-10-11 12:48:49 +02:00
1 parent 2eb1ba22cf
commit 89d37e62e1
7 files changed
+128 -4

No files matched your search

+95 -3
View File
@@ -19,7 +19,8 @@ jobs:
# Same job as in pr-compile-check.yml, copied rather than shared: a reusable workflow
# would be one more indirection to read, and the comments belong next to the steps they
# explain. Every packaging job below needs this one, so a commit whose tests fail builds
# no artifact (#62). Edit all three copies together.
# no artifact (#62). Edit all three copies together -- except for the tag check
# right after the checkout, which only makes sense here.
test:
name: Test (Java 21, headless)
runs-on: ubuntu-latest
@@ -28,6 +29,33 @@ jobs:
- name: Checkout
uses: actions/checkout@v7
# composePackageVersion is the package version of every Compose target format,
# and the Linux package release below is derived from the tag alone. A tag that
# names a different X.Y.Z than gradle.properties would therefore ship packages
# whose version contradicts their file name and upgrade order (#113). Fail
# before the tests rather than after an hour of packaging. Skipped for
# workflow_dispatch, where the ref is a branch and carries no version.
- name: Verify the tag matches composePackageVersion
if: github.ref_type == 'tag'
env:
REF_NAME: ${{ github.ref_name }}
run: |
set -euo pipefail
if [[ "$REF_NAME" =~ ^v([0-9]+\.[0-9]+\.[0-9]+)$ ]]; then
TAG_VERSION="${BASH_REMATCH[1]}"
elif [[ "$REF_NAME" =~ ^beta-v([0-9]+\.[0-9]+\.[0-9]+)-.+$ ]]; then
TAG_VERSION="${BASH_REMATCH[1]}"
else
echo "::error::Tag '$REF_NAME' is neither vX.Y.Z nor beta-vX.Y.Z-<suffix>, so it carries no package version"
exit 1
fi
PROPERTY_VERSION="$(sed -n 's/^composePackageVersion=//p' gradle.properties)"
if [[ "$TAG_VERSION" != "$PROPERTY_VERSION" ]]; then
echo "::error::Tag $REF_NAME names version $TAG_VERSION, but gradle.properties has composePackageVersion=$PROPERTY_VERSION. Bump composePackageVersion (and version) before tagging, or move the tag."
exit 1
fi
echo "Tag $REF_NAME matches composePackageVersion=$PROPERTY_VERSION"
- name: Set up Java 21
uses: actions/setup-java@v6.0.1
with:
@@ -269,9 +297,41 @@ jobs:
- name: Ensure gradlew is executable
run: chmod +x gradlew
# rpm and dpkg refuse to replace a package by one of equal version, and the
# version is composePackageVersion for beta and stable alike. The package
# RELEASE number tells them apart, following the Fedora pre-release convention:
# beta-v1.50.0-beta-001 -> 1.50.0-0.beta.001, beta-v1.50.0-rc02 -> 1.50.0-0.rc02,
# v1.50.0 -> 1.50.0-1. Everything starting with "0." sorts below "1", so the
# stable installs as an upgrade over any beta (#113). The beta part is the tag
# remainder after beta-vX.Y.Z- with "-" turned into "."; rpm and dpkg accept
# only [A-Za-z0-9.] there, anything else fails this step. nightly-artifacts.yml
# does not set the property and keeps release 1, as do local builds.
- name: Derive the Linux package release from the tag
env:
REF_NAME: ${{ github.ref_name }}
REF_TYPE: ${{ github.ref_type }}
run: |
set -euo pipefail
if [[ "$REF_TYPE" != "tag" ]]; then
RELEASE="1"
elif [[ "$REF_NAME" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
RELEASE="1"
elif [[ "$REF_NAME" =~ ^beta-v[0-9]+\.[0-9]+\.[0-9]+-(.+)$ ]]; then
RELEASE="0.${BASH_REMATCH[1]//-/.}"
else
echo "::error::Tag '$REF_NAME' is neither vX.Y.Z nor beta-vX.Y.Z-<suffix>, so no package release can be derived"
exit 1
fi
if [[ ! "$RELEASE" =~ ^[A-Za-z0-9.]+$ ]]; then
echo "::error::Derived package release '$RELEASE' contains characters rpm and dpkg do not accept"
exit 1
fi
echo "Linux package release for $REF_NAME: $RELEASE"
echo "LINUX_APP_RELEASE=$RELEASE" >> "$GITHUB_ENV"
- name: Build Debian package
run: |
./gradlew -S :app-desktop:packageDeb
./gradlew -S :app-desktop:packageDeb -PlinuxAppRelease="$LINUX_APP_RELEASE"
mkdir -p dist
DEB="$(ls app-desktop/build/compose/binaries/main/deb/*.deb | head -n 1)"
if [ -z "$DEB" ]; then
@@ -308,9 +368,41 @@ jobs:
- name: Ensure gradlew is executable
run: chmod +x gradlew
# rpm and dpkg refuse to replace a package by one of equal version, and the
# version is composePackageVersion for beta and stable alike. The package
# RELEASE number tells them apart, following the Fedora pre-release convention:
# beta-v1.50.0-beta-001 -> 1.50.0-0.beta.001, beta-v1.50.0-rc02 -> 1.50.0-0.rc02,
# v1.50.0 -> 1.50.0-1. Everything starting with "0." sorts below "1", so the
# stable installs as an upgrade over any beta (#113). The beta part is the tag
# remainder after beta-vX.Y.Z- with "-" turned into "."; rpm and dpkg accept
# only [A-Za-z0-9.] there, anything else fails this step. nightly-artifacts.yml
# does not set the property and keeps release 1, as do local builds.
- name: Derive the Linux package release from the tag
env:
REF_NAME: ${{ github.ref_name }}
REF_TYPE: ${{ github.ref_type }}
run: |
set -euo pipefail
if [[ "$REF_TYPE" != "tag" ]]; then
RELEASE="1"
elif [[ "$REF_NAME" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
RELEASE="1"
elif [[ "$REF_NAME" =~ ^beta-v[0-9]+\.[0-9]+\.[0-9]+-(.+)$ ]]; then
RELEASE="0.${BASH_REMATCH[1]//-/.}"
else
echo "::error::Tag '$REF_NAME' is neither vX.Y.Z nor beta-vX.Y.Z-<suffix>, so no package release can be derived"
exit 1
fi
if [[ ! "$RELEASE" =~ ^[A-Za-z0-9.]+$ ]]; then
echo "::error::Derived package release '$RELEASE' contains characters rpm and dpkg do not accept"
exit 1
fi
echo "Linux package release for $REF_NAME: $RELEASE"
echo "LINUX_APP_RELEASE=$RELEASE" >> "$GITHUB_ENV"
- name: Build Fedora package
run: |
./gradlew -S :app-desktop:packageRpm
./gradlew -S :app-desktop:packageRpm -PlinuxAppRelease="$LINUX_APP_RELEASE"
mkdir -p dist
RPM="$(ls app-desktop/build/compose/binaries/main/rpm/*.rpm | head -n 1)"
if [ -z "$RPM" ]; then