Windows MSI installer next to the portable ZIP (#61) (#111)

* build: configure the Windows MSI installer in the Compose windows block (#61)

Add the jpackage/WiX options for a per-user MSI next to the existing
icon: a fixed upgradeUuid so Windows Installer replaces an installed
KST4Contest instead of installing side by side, a Start menu group and
desktop shortcut, no UAC prompt, and a directory chooser. The portable
ZIP (createDistributable) is unaffected; the MSI is produced only by
the tagged-release workflow.

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

* ci: build and attach a Windows MSI installer for tagged releases (#61)

The Windows job of tagged-release.yml now runs packageMsi after the
portable ZIP, renames the result to KST4Contest-<tag>-windows-x64.msi
(consistent with the other platforms; the ZIP keeps its praktiKST name)
and uploads it as the windows-msi artifact, which the release job
downloads and attaches next to the ZIP. The nightly workflow stays
ZIP-only because a nightly MSI would always carry the same version.

The website download data (downloads.js, beta.js) gets an MSI card that
is shown only when the release actually has that asset, so the page
never links to a file that does not exist for an older release.

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

* docs: describe the Windows MSI installer next to the portable ZIP (#61)

The German and English installation manuals list the MSI in the package
table, describe both Windows forms (installer: per user, Start menu
entry, desktop shortcut, chosen directory, in-place upgrade, removal via
the Windows apps list; ZIP: portable) and the shared data directory
%USERPROFILE%\.praktiKST, and add the MSI path to the Windows update
section. Changelog entries for v1.50 and a note in PROJECT_CONTEXT.md
record the fixed upgrade UUID and the tags-only decision.

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

* ci: build the Windows MSI for stable tags only (#61)

A beta MSI would carry the same composePackageVersion as the following
stable release. jpackage's MSI upgrade table only accepts strictly higher
versions, so Windows Installer would refuse the stable over an installed
beta and the tester would have to uninstall first. Betas therefore stay
ZIP-only like nightlies; the build, upload and download steps are skipped
for beta- tags, and the release action tolerates the missing asset path.
Manual, changelog and project context say so.

Raised by the Codex review on #111.

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:27:43 +02:00
1 parent 5491cbcf8b
commit 2eb1ba22cf
9 files changed
+189 -17

No files matched your search

+38 -1
View File
@@ -111,7 +111,7 @@ jobs:
retention-days: 7 retention-days: 7
build-windows-zip: build-windows-zip:
name: Build Windows ZIP name: Build Windows ZIP and MSI
runs-on: windows-latest runs-on: windows-latest
needs: test needs: test
@@ -153,6 +153,32 @@ jobs:
name: windows-zip name: windows-zip
path: dist/praktiKST-${{ github.ref_name }}-windows-x64.zip path: dist/praktiKST-${{ github.ref_name }}-windows-x64.zip
# Stable tags only (issue #61): the MSI carries composePackageVersion
# from gradle.properties, so a nightly or beta MSI would have the same
# version as the following stable one. Windows Installer refuses to
# install an equal version over the installed one (jpackage's upgrade
# table only accepts strictly higher versions), so a beta tester could
# not move to the stable without uninstalling first. Betas and nightlies
# therefore stay ZIP-only. jpackage needs WiX 3.x, installed above. The
# ZIP is unchanged and stays alongside.
- name: Build Windows MSI installer
if: ${{ !startsWith(github.ref_name, 'beta-') }}
shell: pwsh
run: |
.\gradlew.bat -S :app-desktop:packageMsi
$msi = Get-ChildItem -Path app-desktop/build/compose/binaries/main/msi -Filter *.msi -ErrorAction SilentlyContinue | Select-Object -First 1
if (-not $msi) {
throw "No Windows MSI produced by packageMsi"
}
Copy-Item $msi.FullName dist/KST4Contest-${{ github.ref_name }}-windows-x64.msi
- name: Upload Windows MSI artifact
if: ${{ !startsWith(github.ref_name, 'beta-') }}
uses: actions/upload-artifact@v6
with:
name: windows-msi
path: dist/KST4Contest-${{ github.ref_name }}-windows-x64.msi
build-linux-appimage: build-linux-appimage:
name: Build Linux AppImage name: Build Linux AppImage
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -835,6 +861,13 @@ jobs:
name: windows-zip name: windows-zip
path: release-assets/windows path: release-assets/windows
- name: Download Windows MSI artifact
if: ${{ !startsWith(github.ref_name, 'beta-') }}
uses: actions/download-artifact@v8.0.1
with:
name: windows-msi
path: release-assets/windows
- name: Download Linux artifact - name: Download Linux artifact
uses: actions/download-artifact@v8.0.1 uses: actions/download-artifact@v8.0.1
with: with:
@@ -890,8 +923,12 @@ jobs:
makeLatest: ${{ !startsWith(github.ref_name, 'beta-') }} makeLatest: ${{ !startsWith(github.ref_name, 'beta-') }}
bodyFile: release-notes.md bodyFile: release-notes.md
generateReleaseNotes: false generateReleaseNotes: false
# The MSI entry is absent for beta tags (the Windows job skips it);
# artifactErrorsFailBuild is left at its default, so a missing path
# only warns and the release still gets every other asset.
artifacts: >- artifacts: >-
release-assets/windows/praktiKST-${{ github.ref_name }}-windows-x64.zip, release-assets/windows/praktiKST-${{ github.ref_name }}-windows-x64.zip,
release-assets/windows/KST4Contest-${{ github.ref_name }}-windows-x64.msi,
release-assets/linux/KST4Contest-${{ github.ref_name }}-linux-x86_64.AppImage, release-assets/linux/KST4Contest-${{ github.ref_name }}-linux-x86_64.AppImage,
release-assets/debian/KST4Contest-${{ github.ref_name }}-debian-amd64.deb, release-assets/debian/KST4Contest-${{ github.ref_name }}-debian-amd64.deb,
release-assets/fedora/KST4Contest-${{ github.ref_name }}-fedora-x86_64.rpm, release-assets/fedora/KST4Contest-${{ github.ref_name }}-fedora-x86_64.rpm,
+21 -1
View File
@@ -144,7 +144,27 @@ compose.desktop {
) )
linux { iconFile.set(rootProject.file("packaging/icons/kst4contest.png")) } linux { iconFile.set(rootProject.file("packaging/icons/kst4contest.png")) }
windows { iconFile.set(rootProject.file("packaging/icons/kst4contest.ico")) } windows {
iconFile.set(rootProject.file("packaging/icons/kst4contest.ico"))
/*
* The MSI installer is built for tagged releases only; nightlies ship
* the portable ZIP alone, because an MSI always carries the plain
* composePackageVersion and two nightly MSIs could not be told apart.
* It installs per user, so it needs neither administrator rights nor
* a UAC prompt, and it adds a Start menu group and a desktop shortcut.
*
* upgradeUuid must NEVER change: Windows Installer uses it to
* recognise an installed KST4Contest and replace it in place when a
* newer MSI runs. A different value would install the new release
* side by side with the old one instead of upgrading it.
*/
upgradeUuid = "3375071a-25ba-468e-9ae5-8296bc535462"
menu = true
menuGroup = "KST4Contest"
shortcut = true
perUserInstall = true
dirChooser = true
}
macOS { macOS {
iconFile.set(rootProject.file("packaging/icons/kst4contest.icns")) iconFile.set(rootProject.file("packaging/icons/kst4contest.icns"))
// Must stay de.x08.KST4Contest: build-signed-dmg.sh signs against it. // Must stay de.x08.KST4Contest: build-signed-dmg.sh signs against it.
+1
View File
@@ -225,6 +225,7 @@ Current website/deployment scripts and update-feed behaviour must be inspected b
- `APPLICATION_CURRENT_VERSION` is the user-visible semantic version and must use the dotted `major.minor.patch` form. `APPLICATION_CURRENTVERSIONNUMBER` is retained only for older feeds and encodes patch releases by appending the patch digit, for example `1.43.1` as `1.431`. - `APPLICATION_CURRENT_VERSION` is the user-visible semantic version and must use the dotted `major.minor.patch` form. `APPLICATION_CURRENTVERSIONNUMBER` is retained only for older feeds and encodes patch releases by appending the patch digit, for example `1.43.1` as `1.431`.
- The tagged-release workflow creates the GitHub Release before building the website update feed. This ordering is required because `versionInfo.js` reads the published release body through the GitHub Releases API. - The tagged-release workflow creates the GitHub Release before building the website update feed. This ordering is required because `versionInfo.js` reads the published release body through the GitHub Releases API.
- Stable tags ship a Windows MSI installer (`KST4Contest-<tag>-windows-x64.msi`, Compose `packageMsi`, jpackage with WiX 3) next to the unchanged portable ZIP (issue #61). It installs per user without UAC and carries the fixed `upgradeUuid` in `app-desktop/build.gradle.kts`, which must never change because Windows Installer uses it to replace the installed version. Nightlies and beta tags stay ZIP-only: an MSI always carries `composePackageVersion`, so a nightly or beta MSI would have the same version as the following stable one, and jpackage's upgrade table only accepts strictly higher versions, so Windows Installer would refuse the stable over an installed beta. Installed and portable copies share `~/.praktiKST`. The website download data (`downloads.js`, `beta.js`) lists the MSI only when the release actually has that asset.
- After publication, the workflow tests and builds the website, validates the expected Stable version, attaches `kst4ContestVersionInfo.xml` to the release and uploads the complete website build as a workflow artifact. - After publication, the workflow tests and builds the website, validates the expected Stable version, attaches `kst4ContestVersionInfo.xml` to the release and uploads the complete website build as a workflow artifact.
### Server-side website statistics ### Server-side website statistics
+2
View File
@@ -24,6 +24,8 @@ Mehrere Operateure an einem Rechner können jetzt eigene Rufzeichen, Locators un
- **Profilwechsel im laufenden Betrieb:** **File → Switch operator profile...** trennt die Verbindung und baut die Oberfläche mit den Einstellungen des gewählten Profils neu auf, ohne Programmneustart. - **Profilwechsel im laufenden Betrieb:** **File → Switch operator profile...** trennt die Verbindung und baut die Oberfläche mit den Einstellungen des gewählten Profils neu auf, ohne Programmneustart.
- **Windows-Installer:** Neben dem portablen ZIP-Paket gibt es für Windows bei Stable-Releases jetzt einen MSI-Installer (`KST4Contest-v<Version>-windows-x64.msi`). Er installiert KST4Contest ohne Administratorrechte für das aktuelle Benutzerkonto, legt einen Startmenü-Eintrag und eine Desktop-Verknüpfung an und ersetzt bei einem Update die vorhandene Installation. Einstellungen und Datenbank bleiben unter `%USERPROFILE%\.praktiKST` und werden mit einer portablen Kopie geteilt. Damit ist die erste Stufe von [Issue #61](https://github.com/praktimarc/kst4contest/issues/61) umgesetzt.
### Geändert ### Geändert
- **Zwischenspeicher der Geländeprofile getrennt:** Berechnete Geländeprofile liegen jetzt in der eigenen, gemeinsam genutzten Datei `terrainprofilecache.db` und werden nach Besitzer getrennt gespeichert. Bisher wurde der gesamte Zwischenspeicher gelöscht, sobald sich Rufzeichen oder Locator änderten; bei einem Profilwechsel wäre damit jedes berechnete Profil verloren gegangen. - **Zwischenspeicher der Geländeprofile getrennt:** Berechnete Geländeprofile liegen jetzt in der eigenen, gemeinsam genutzten Datei `terrainprofilecache.db` und werden nach Besitzer getrennt gespeichert. Bisher wurde der gesamte Zwischenspeicher gelöscht, sobald sich Rufzeichen oder Locator änderten; bei einem Profilwechsel wäre damit jedes berechnete Profil verloren gegangen.
+36 -6
View File
@@ -65,7 +65,8 @@ Die Release-Seite enthält die Programmpakete sowie die deutschen und englischen
| Betriebssystem | Paket | Typischer Dateiname | | Betriebssystem | Paket | Typischer Dateiname |
|---|---|---| |---|---|---|
| Windows x64 | ZIP-Paket | `praktiKST-v<Version>-windows-x64.zip` | | Windows x64 | MSI-Installer | `KST4Contest-v<Version>-windows-x64.msi` |
| Windows x64 | ZIP-Paket (portabel) | `praktiKST-v<Version>-windows-x64.zip` |
| Linux x86_64 | AppImage | `KST4Contest-v<Version>-linux-x86_64.AppImage` | | Linux x86_64 | AppImage | `KST4Contest-v<Version>-linux-x86_64.AppImage` |
| Debian/Ubuntu amd64 | DEB-Paket | `KST4Contest-v<Version>-debian-amd64.deb` | | Debian/Ubuntu amd64 | DEB-Paket | `KST4Contest-v<Version>-debian-amd64.deb` |
| Fedora/RPM x86_64 | RPM-Paket | `KST4Contest-v<Version>-fedora-x86_64.rpm` | | Fedora/RPM x86_64 | RPM-Paket | `KST4Contest-v<Version>-fedora-x86_64.rpm` |
@@ -80,7 +81,25 @@ Lade Programmpakete nur aus den offiziellen GitHub Releases, dem KST4Contest-Fla
## Installation unter Windows ## Installation unter Windows
KST4Contest wird unter Windows als ZIP-Paket bereitgestellt. Ein klassischer Installer ist nicht erforderlich. KST4Contest wird unter Windows in zwei Formen bereitgestellt: als MSI-Installer und als portables ZIP-Paket. Beide enthalten dasselbe Programm mit derselben Laufzeitumgebung; sie unterscheiden sich nur darin, wie das Programm auf den Rechner kommt. Der MSI-Installer wird nur für Stable-Releases gebaut: Ein Beta-Installer trüge dieselbe Versionsnummer wie das folgende Stable-Release, und Windows Installer verweigert die Installation einer gleichen Version über eine vorhandene. Beta- und Nightly-Versionen gibt es für Windows deshalb nur als ZIP-Paket.
| Form | Sinnvoll, wenn … |
|---|---|
| **MSI-Installer** | KST4Contest wie ein gewöhnliches Windows-Programm mit Startmenü-Eintrag installiert und aktualisiert werden soll |
| **ZIP-Paket** | KST4Contest ohne Installation aus einem beliebigen Ordner gestartet werden soll, etwa von einem USB-Stick |
### MSI-Installer
1. Lade `KST4Contest-v<Version>-windows-x64.msi` aus dem aktuellen Release herunter.
2. Starte die heruntergeladene Datei.
3. Behalte den vorgeschlagenen Installationsordner oder wähle einen anderen und schließe den Installer ab.
4. Starte KST4Contest über den Startmenü-Eintrag in der Gruppe **KST4Contest** oder über die Desktop-Verknüpfung.
Der Installer richtet KST4Contest nur für das aktuelle Windows-Benutzerkonto ein. Administratorrechte sind nicht erforderlich, und die Benutzerkontensteuerung fragt nicht nach. Eine neuere Version wird einfach über die vorhandene installiert: Der Installer ersetzt die bisherige Installation, eine vorherige Deinstallation ist nicht nötig. Entfernt wird KST4Contest wie jedes andere Programm über die Windows-Einstellungen unter **Apps → Installierte Apps**.
Der Installer ist nicht mit einem Code-Signing-Zertifikat signiert. Zeigt Windows beim Start eine Warnung, gelten die Hinweise unter [Windows meldet eine unbekannte Anwendung](#windows-meldet-eine-unbekannte-anwendung).
### ZIP-Paket
1. Lade `praktiKST-v<Version>-windows-x64.zip` aus dem aktuellen Release herunter. 1. Lade `praktiKST-v<Version>-windows-x64.zip` aus dem aktuellen Release herunter.
2. Entpacke die ZIP-Datei vollständig in einen eigenen Ordner. 2. Entpacke die ZIP-Datei vollständig in einen eigenen Ordner.
@@ -89,13 +108,15 @@ KST4Contest wird unter Windows als ZIP-Paket bereitgestellt. Ein klassischer Ins
Starte das Programm nicht direkt aus der noch komprimierten ZIP-Datei. KST4Contest besteht aus mehreren Dateien und einer mitgelieferten Laufzeitumgebung. Windows kann diese Struktur nur zuverlässig verwenden, wenn das Archiv vorher vollständig entpackt wurde. Starte das Programm nicht direkt aus der noch komprimierten ZIP-Datei. KST4Contest besteht aus mehreren Dateien und einer mitgelieferten Laufzeitumgebung. Windows kann diese Struktur nur zuverlässig verwenden, wenn das Archiv vorher vollständig entpackt wurde.
Die Programmeinstellungen befinden sich nicht im entpackten Programmordner, sondern im Benutzerverzeichnis: ### Einstellungen und Daten
Die Programmeinstellungen und die Datenbank der gearbeiteten Stationen befinden sich bei beiden Formen nicht im Programmordner, sondern im Benutzerverzeichnis:
```text ```text
%USERPROFILE%\.praktiKST\preferences.xml %USERPROFILE%\.praktiKST\
``` ```
Dadurch können neue Programmversionen in einen anderen Ordner entpackt werden, ohne dass die vorhandenen Einstellungen verloren gehen. Dadurch können neue Programmversionen installiert oder in einen anderen Ordner entpackt werden, ohne dass die vorhandenen Einstellungen verloren gehen. Eine installierte und eine portable Kopie auf demselben Rechner verwenden dieselben Einstellungen und dieselbe Datenbank.
--- ---
@@ -325,6 +346,15 @@ Der Update-Checker installiert nichts selbst. Er informiert über die neue Versi
### Windows aktualisieren ### Windows aktualisieren
**MSI-Installer**
1. Beende KST4Contest.
2. Lade die neue MSI-Datei herunter und starte sie.
3. Der Installer ersetzt die vorhandene Installation; Startmenü-Eintrag und Desktop-Verknüpfung bleiben erhalten.
4. Starte die neue Version und prüfe, ob die bisherigen Einstellungen geladen wurden.
**ZIP-Paket**
1. Beende KST4Contest. 1. Beende KST4Contest.
2. Lade das neue Windows-ZIP herunter. 2. Lade das neue Windows-ZIP herunter.
3. Entpacke es in einen neuen oder leeren Ordner. 3. Entpacke es in einen neuen oder leeren Ordner.
@@ -332,7 +362,7 @@ Der Update-Checker installiert nichts selbst. Er informiert über die neue Versi
5. Prüfe, ob die bisherigen Einstellungen geladen wurden. 5. Prüfe, ob die bisherigen Einstellungen geladen wurden.
6. Entferne den alten Programmordner erst danach. 6. Entferne den alten Programmordner erst danach.
Die Einstellungen bleiben erhalten, weil sie unter `%USERPROFILE%\.praktiKST` und nicht im Programmordner gespeichert werden. Die Einstellungen bleiben in beiden Fällen erhalten, weil sie unter `%USERPROFILE%\.praktiKST` und nicht im Programmordner gespeichert werden.
### AppImage aktualisieren ### AppImage aktualisieren
+2
View File
@@ -24,6 +24,8 @@ Several operators sharing one computer can now use their own callsigns, locators
- **Switching profiles while running:** **File > Switch operator profile...** closes the connection and rebuilds the user interface with the settings of the selected profile, without restarting the program. - **Switching profiles while running:** **File > Switch operator profile...** closes the connection and rebuilds the user interface with the settings of the selected profile, without restarting the program.
- **Windows installer:** next to the portable ZIP package, stable releases now also ship an MSI installer for Windows (`KST4Contest-v<version>-windows-x64.msi`). It installs KST4Contest for the current user account without administrator rights, adds a Start menu entry and a desktop shortcut, and replaces the existing installation on an update. Settings and database stay under `%USERPROFILE%\.praktiKST` and are shared with a portable copy. This implements the first stage of [Issue #61](https://github.com/praktimarc/kst4contest/issues/61).
### Changed ### Changed
- **The terrain profile cache is separate:** computed terrain profiles now live in their own shared file `terrainprofilecache.db` and are stored per owner. Previously the whole cache was dropped whenever the callsign or locator changed, which would have discarded every computed profile on each profile switch. - **The terrain profile cache is separate:** computed terrain profiles now live in their own shared file `terrainprofilecache.db` and are stored per owner. Previously the whole cache was dropped whenever the callsign or locator changed, which would have discarded every computed profile on each profile switch.
+36 -6
View File
@@ -65,7 +65,8 @@ The release page contains the application packages as well as the English and Ge
| Operating system | Package | Typical filename | | Operating system | Package | Typical filename |
|---|---|---| |---|---|---|
| Windows x64 | ZIP package | `praktiKST-v<version>-windows-x64.zip` | | Windows x64 | MSI installer | `KST4Contest-v<version>-windows-x64.msi` |
| Windows x64 | ZIP package (portable) | `praktiKST-v<version>-windows-x64.zip` |
| Linux x86_64 | AppImage | `KST4Contest-v<version>-linux-x86_64.AppImage` | | Linux x86_64 | AppImage | `KST4Contest-v<version>-linux-x86_64.AppImage` |
| Debian/Ubuntu amd64 | DEB package | `KST4Contest-v<version>-debian-amd64.deb` | | Debian/Ubuntu amd64 | DEB package | `KST4Contest-v<version>-debian-amd64.deb` |
| Fedora/RPM x86_64 | RPM package | `KST4Contest-v<version>-fedora-x86_64.rpm` | | Fedora/RPM x86_64 | RPM package | `KST4Contest-v<version>-fedora-x86_64.rpm` |
@@ -80,7 +81,25 @@ Only download application packages from the official GitHub Releases, the KST4Co
## Installing on Windows ## Installing on Windows
KST4Contest is distributed as a ZIP package for Windows. A conventional installer is not required. KST4Contest is distributed for Windows in two forms: as an MSI installer and as a portable ZIP package. Both contain the same application with the same bundled runtime; they differ only in how the application gets onto the computer. The MSI installer is built for stable releases only: a beta installer would carry the same version number as the following stable release, and Windows Installer refuses to install an equal version over an installed one. Beta and nightly builds for Windows are therefore provided as the ZIP package only.
| Form | Useful when … |
|---|---|
| **MSI installer** | KST4Contest should be installed and updated like an ordinary Windows application, with a Start menu entry |
| **ZIP package** | KST4Contest should run from any folder without installation, for example from a USB stick |
### MSI installer
1. Download `KST4Contest-v<version>-windows-x64.msi` from the latest release.
2. Start the downloaded file.
3. Keep the suggested installation folder or choose a different one, then finish the installer.
4. Start KST4Contest from the Start menu entry in the **KST4Contest** group or from the desktop shortcut.
The installer sets up KST4Contest for the current Windows user account only. Administrator rights are not required, and User Account Control does not ask for confirmation. A newer version is simply installed over the existing one: the installer replaces the previous installation, so there is no need to uninstall first. KST4Contest is removed like any other application through the Windows settings under **Apps → Installed apps**.
The installer is not signed with a code-signing certificate. If Windows shows a warning when it starts, the notes under [Windows reports an unknown application](#windows-reports-an-unknown-application) apply.
### ZIP package
1. Download `praktiKST-v<version>-windows-x64.zip` from the latest release. 1. Download `praktiKST-v<version>-windows-x64.zip` from the latest release.
2. Extract the ZIP file completely into a dedicated folder. 2. Extract the ZIP file completely into a dedicated folder.
@@ -89,13 +108,15 @@ KST4Contest is distributed as a ZIP package for Windows. A conventional installe
Do not start the application directly from the compressed ZIP file. KST4Contest consists of several files and a bundled runtime. Windows can only use this structure reliably after the archive has been extracted completely. Do not start the application directly from the compressed ZIP file. KST4Contest consists of several files and a bundled runtime. Windows can only use this structure reliably after the archive has been extracted completely.
The application settings are not stored in the extracted program directory. They are stored in your user profile: ### Settings and data
With both forms, the application settings and the worked-stations database are not stored in the program directory. They are stored in your user profile:
```text ```text
%USERPROFILE%\.praktiKST\preferences.xml %USERPROFILE%\.praktiKST\
``` ```
This allows a new application version to be extracted into a different directory without losing the existing settings. This allows a new application version to be installed or extracted into a different directory without losing the existing settings. An installed copy and a portable copy on the same computer use the same settings and the same database.
--- ---
@@ -325,6 +346,15 @@ The update checker does not install anything. It reports the new version and ope
### Updating Windows ### Updating Windows
**MSI installer**
1. Close KST4Contest.
2. Download the new MSI file and start it.
3. The installer replaces the existing installation; the Start menu entry and the desktop shortcut are kept.
4. Start the new version and check that the existing settings have been loaded.
**ZIP package**
1. Close KST4Contest. 1. Close KST4Contest.
2. Download the new Windows ZIP package. 2. Download the new Windows ZIP package.
3. Extract it into a new or empty directory. 3. Extract it into a new or empty directory.
@@ -332,7 +362,7 @@ The update checker does not install anything. It reports the new version and ope
5. Check that the existing settings have been loaded. 5. Check that the existing settings have been loaded.
6. Remove the old application directory only after that. 6. Remove the old application directory only after that.
The settings are preserved because they are stored under `%USERPROFILE%\.praktiKST`, not in the application directory. In both cases the settings are preserved because they are stored under `%USERPROFILE%\.praktiKST`, not in the application directory.
### Updating an AppImage ### Updating an AppImage
+16
View File
@@ -82,6 +82,21 @@ module.exports = async function () {
const assetUrl = (filenameTemplate) => const assetUrl = (filenameTemplate) =>
`https://github.com/${REPO}/releases/download/${tag}/${filenameTemplate.replace(/\{tag\}/g, tag)}`; `https://github.com/${REPO}/releases/download/${tag}/${filenameTemplate.replace(/\{tag\}/g, tag)}`;
// The MSI installer exists for tags from version 1.50 onwards (issue #61);
// an older beta release has no such asset and gets no dead link.
const assetNames = (release.assets || []).map((asset) => asset.name);
const windowsMsi = assetNames.includes(`KST4Contest-${tag}-windows-x64.msi`)
? [
{
os: "Windows",
format: "MSI installer x64",
icon: "🪟",
note: "Installs for the current user without administrator rights, with a Start menu entry and a desktop shortcut. Settings are shared with the ZIP version.",
url: assetUrl("KST4Contest-{tag}-windows-x64.msi")
}
]
: [];
const items = [ const items = [
{ {
os: "Windows", os: "Windows",
@@ -90,6 +105,7 @@ module.exports = async function () {
note: "Extract the archive, then start praktiKST.exe. No separate Java installation is required.", note: "Extract the archive, then start praktiKST.exe. No separate Java installation is required.",
url: assetUrl("praktiKST-{tag}-windows-x64.zip") url: assetUrl("praktiKST-{tag}-windows-x64.zip")
}, },
...windowsMsi,
{ {
os: "Linux", os: "Linux",
format: "Flatpak (.flatpakref)", format: "Flatpak (.flatpakref)",
+37 -3
View File
@@ -2,7 +2,11 @@ const REPO = "praktimarc/kst4contest";
const API = `https://api.github.com/repos/${REPO}`; const API = `https://api.github.com/repos/${REPO}`;
const LATEST_RELEASE_URL = `https://github.com/${REPO}/releases/latest`; const LATEST_RELEASE_URL = `https://github.com/${REPO}/releases/latest`;
async function fetchLatestReleaseTag() { /**
* Loads the latest Stable release: its tag and the names of its assets.
* Returns null if the GitHub API was unavailable.
*/
async function fetchLatestRelease() {
const headers = { Accept: "application/vnd.github+json" }; const headers = { Accept: "application/vnd.github+json" };
if (process.env.GITHUB_TOKEN) { if (process.env.GITHUB_TOKEN) {
@@ -26,7 +30,10 @@ async function fetchLatestReleaseTag() {
); );
} }
return release.tag_name; return {
tag: release.tag_name,
assetNames: (release.assets || []).map((asset) => asset.name)
};
} catch (err) { } catch (err) {
console.warn( console.warn(
`[downloads] Could not load the latest release tag. ` + `[downloads] Could not load the latest release tag. ` +
@@ -61,10 +68,36 @@ function createAssetUrl(latestTag, filenameTemplate) {
* .github/workflows/tagged-release.yml. * .github/workflows/tagged-release.yml.
*/ */
module.exports = async function () { module.exports = async function () {
const latestTag = await fetchLatestReleaseTag(); const release = await fetchLatestRelease();
const latestTag = release ? release.tag : null;
const assetUrl = (filenameTemplate) => const assetUrl = (filenameTemplate) =>
createAssetUrl(latestTag, filenameTemplate); createAssetUrl(latestTag, filenameTemplate);
/*
* The MSI installer exists for tagged releases from version 1.50 onwards
* (issue #61). Until a Stable release carries one, its card is omitted
* rather than pointing at a file that does not exist. Without API data
* the card is kept: its link then opens the release page like all others.
*/
const hasAsset = (filenameTemplate) =>
!release ||
release.assetNames.includes(
filenameTemplate.replace(/\{tag\}/g, release.tag)
);
const windowsMsi = hasAsset("KST4Contest-{tag}-windows-x64.msi")
? [
{
os: "Windows",
format: "MSI installer x64",
icon: "🪟",
recommended: false,
note: "Installs for the current user without administrator rights, with a Start menu entry and a desktop shortcut. Settings are shared with the ZIP version.",
url: assetUrl("KST4Contest-{tag}-windows-x64.msi")
}
]
: [];
return [ return [
{ {
os: "Windows", os: "Windows",
@@ -74,6 +107,7 @@ module.exports = async function () {
note: "Extract the complete archive, then start praktiKST.exe. No separate Java installation is required.", note: "Extract the complete archive, then start praktiKST.exe. No separate Java installation is required.",
url: assetUrl("praktiKST-{tag}-windows-x64.zip") url: assetUrl("praktiKST-{tag}-windows-x64.zip")
}, },
...windowsMsi,
{ {
os: "Linux", os: "Linux",
format: "Flatpak (.flatpakref)", format: "Flatpak (.flatpakref)",