mirror of
https://github.com/pepaskopec-blip/Graduately.git
synced 2026-10-27 07:04:35 +00:00
Add installers that fetch the newest release when run.
Each installer carries no application of its own and resolves /releases/latest/download/ at the moment it runs, so the file never goes stale and the same download keeps working across future releases. macOS installs into /Applications, falling back to the user's own folder when that is not writable, and clears the quarantine flag the unsigned build would otherwise trip over. Windows extracts over any existing install rather than replacing the folder, so the progress files kept inside it survive, and adds a Start menu entry. Linux drops the AppImage in ~/Applications with a desktop entry and its icon. Publish the macOS one zipped, because a release asset loses its executable bit and a .command needs one to be double-clicked. The .cmd also had to be excluded from the *.cmd ignore rule, which comes from the kernel section of the template and targets build artifacts. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
91a848b408
commit
7d503d6c5b
6 changed files with 286 additions and 0 deletions
14
.github/workflows/release.yml
vendored
14
.github/workflows/release.yml
vendored
|
|
@ -111,6 +111,17 @@ jobs:
|
|||
path: release-assets
|
||||
merge-multiple: true
|
||||
|
||||
# The installers carry no application: each downloads the newest release
|
||||
# when the user runs it. The macOS one is zipped because a release asset
|
||||
# loses its executable bit, which a .command needs to be double-clicked.
|
||||
- name: Collect installers
|
||||
run: |
|
||||
cp installers/maturita-installer-linux.sh release-assets/
|
||||
cp installers/maturita-installer-windows.cmd release-assets/
|
||||
chmod +x installers/maturita-installer-macos.command
|
||||
(cd installers && zip -q ../release-assets/maturita-installer-macos.zip \
|
||||
maturita-installer-macos.command)
|
||||
|
||||
- name: List assets
|
||||
run: find release-assets -type f -print
|
||||
|
||||
|
|
@ -121,6 +132,9 @@ jobs:
|
|||
release-assets/maturita-linux-*.AppImage
|
||||
release-assets/maturita-windows-x64.zip
|
||||
release-assets/maturita-macos-*.zip
|
||||
release-assets/maturita-installer-macos.zip
|
||||
release-assets/maturita-installer-windows.cmd
|
||||
release-assets/maturita-installer-linux.sh
|
||||
generate_release_notes: true
|
||||
fail_on_unmatched_files: true
|
||||
env:
|
||||
|
|
|
|||
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -63,6 +63,9 @@ assets/icons/
|
|||
# Kernel Module Compile Results
|
||||
*.mod*
|
||||
*.cmd
|
||||
# The rule above targets kernel build artifacts such as .foo.o.cmd; the
|
||||
# Windows installer is a source file that has to be tracked.
|
||||
!installers/*.cmd
|
||||
.tmp_versions/
|
||||
modules.order
|
||||
Module.symvers
|
||||
|
|
|
|||
36
README.md
36
README.md
|
|
@ -139,6 +139,24 @@ are required:
|
|||
Progress and settings are saved next to the AppImage / `.app` / unzipped
|
||||
folder in a `progress/` directory.
|
||||
|
||||
#### Installers
|
||||
|
||||
Each release also ships a small installer that contains no application of its
|
||||
own: it downloads the newest build when you run it, so the file never goes out
|
||||
of date. Once installed, the app keeps itself up to date on its own — it checks
|
||||
shortly after startup and offers the update in a banner, and there is a manual
|
||||
check under **Settings → Updates**.
|
||||
|
||||
| Platform | Asset | How to run |
|
||||
| -------- | ----- | ---------- |
|
||||
| macOS (Apple Silicon) | `maturita-installer-macos.zip` | Unzip, then double-click the `.command` file |
|
||||
| Windows (x64) | `maturita-installer-windows.cmd` | Double-click the file |
|
||||
| Linux (x86_64) | `maturita-installer-linux.sh` | `sh maturita-installer-linux.sh` |
|
||||
|
||||
The builds are not code-signed, so the first launch needs one extra step:
|
||||
on macOS right-click the installer and pick **Open**, and on Windows choose
|
||||
**More info → Run anyway** if SmartScreen appears.
|
||||
|
||||
To cut a release yourself (needs a GitHub remote with Actions enabled):
|
||||
|
||||
```bash
|
||||
|
|
@ -600,6 +618,24 @@ při pushi tagu `v*`. Kompilátor ani vývojové balíčky GTK nejsou potřeba:
|
|||
Postup a nastavení se ukládají vedle AppImage / `.app` / rozbalené složky
|
||||
do adresáře `progress/`.
|
||||
|
||||
#### Instalátory
|
||||
|
||||
Ke každému releasu vychází i malý instalátor, který samotnou aplikaci
|
||||
neobsahuje: nejnovější build si stáhne až při spuštění, takže soubor nikdy
|
||||
nezestárne. Nainstalovaná aplikace se pak udržuje aktuální sama — chvíli po
|
||||
startu zkontroluje nové verze a nabídne je v pruhu nahoře, ruční kontrola je
|
||||
v **Nastavení → Aktualizace**.
|
||||
|
||||
| Platforma | Soubor | Spuštění |
|
||||
| --------- | ------ | -------- |
|
||||
| macOS (Apple Silicon) | `maturita-installer-macos.zip` | Rozbalit a dvojklik na soubor `.command` |
|
||||
| Windows (x64) | `maturita-installer-windows.cmd` | Dvojklik na soubor |
|
||||
| Linux (x86_64) | `maturita-installer-linux.sh` | `sh maturita-installer-linux.sh` |
|
||||
|
||||
Buildy nejsou podepsané, takže první spuštění chce jeden krok navíc: na macOS
|
||||
klikněte na instalátor pravým tlačítkem a zvolte **Otevřít**, na Windows při
|
||||
hlášce SmartScreenu **Další informace → Přesto spustit**.
|
||||
|
||||
Vytvoření releasu (GitHub remote s Actions):
|
||||
|
||||
```bash
|
||||
|
|
|
|||
79
installers/maturita-installer-linux.sh
Executable file
79
installers/maturita-installer-linux.sh
Executable file
|
|
@ -0,0 +1,79 @@
|
|||
#!/bin/sh
|
||||
# maturita.c installer for Linux.
|
||||
#
|
||||
# Carries no application of its own: it downloads whatever the newest release
|
||||
# is at the moment you run it, so this file never goes stale. GitHub resolves
|
||||
# the /releases/latest/download/ path to the current tag on every request.
|
||||
#
|
||||
# Run it with: sh maturita-installer-linux.sh
|
||||
# The app updates itself from then on.
|
||||
|
||||
set -eu
|
||||
|
||||
REPO="pepaskopec-blip/maturita.c"
|
||||
ASSET="maturita-linux-x86_64.AppImage"
|
||||
URL="https://github.com/$REPO/releases/latest/download/$ASSET"
|
||||
|
||||
# ~/Applications is where desktop environments look for AppImages, and the app
|
||||
# keeps its progress/ directory next to its own file.
|
||||
DEST_DIR="$HOME/Applications"
|
||||
DEST="$DEST_DIR/maturita.AppImage"
|
||||
DESKTOP_DIR="$HOME/.local/share/applications"
|
||||
ICON_DIR="$HOME/.local/share/icons/hicolor/512x512/apps"
|
||||
|
||||
say() { printf '%s\n' "$*"; }
|
||||
die() { printf '\nError: %s\n' "$*" >&2; exit 1; }
|
||||
|
||||
say "Installing maturita.C"
|
||||
say "---------------------"
|
||||
|
||||
arch=$(uname -m)
|
||||
if [ "$arch" != "x86_64" ]; then
|
||||
die "only x86_64 builds are published, but this machine reports '$arch'.
|
||||
Build from source instead: https://github.com/$REPO"
|
||||
fi
|
||||
|
||||
command -v curl >/dev/null 2>&1 || die "curl was not found. Install it first."
|
||||
|
||||
mkdir -p "$DEST_DIR"
|
||||
|
||||
tmp=$(mktemp -d)
|
||||
trap 'rm -rf "$tmp"' EXIT INT TERM
|
||||
|
||||
say "Downloading the latest release..."
|
||||
curl -fL --progress-bar -o "$tmp/$ASSET" "$URL" ||
|
||||
die "the download failed. Check your internet connection."
|
||||
|
||||
say "Installing to $DEST"
|
||||
chmod +x "$tmp/$ASSET"
|
||||
mv -f "$tmp/$ASSET" "$DEST" || die "could not write to $DEST_DIR."
|
||||
|
||||
# A menu entry needs the icon as a separate file, which the AppImage can
|
||||
# unpack without FUSE. Losing the icon is not worth failing the install over.
|
||||
if (cd "$tmp" && "$DEST" --appimage-extract \
|
||||
'usr/share/icons/hicolor/512x512/apps/maturita.png' >/dev/null 2>&1); then
|
||||
icon="$tmp/squashfs-root/usr/share/icons/hicolor/512x512/apps/maturita.png"
|
||||
if [ -f "$icon" ]; then
|
||||
mkdir -p "$ICON_DIR"
|
||||
cp -f "$icon" "$ICON_DIR/maturita.png"
|
||||
fi
|
||||
fi
|
||||
|
||||
mkdir -p "$DESKTOP_DIR"
|
||||
cat > "$DESKTOP_DIR/maturita.desktop" <<EOF
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=maturita.C
|
||||
Comment=Practice app for the Czech maturita exam
|
||||
Exec=$DEST
|
||||
Icon=maturita
|
||||
Terminal=false
|
||||
Categories=Education;
|
||||
EOF
|
||||
|
||||
command -v update-desktop-database >/dev/null 2>&1 &&
|
||||
update-desktop-database "$DESKTOP_DIR" >/dev/null 2>&1 || true
|
||||
|
||||
say ""
|
||||
say "Done. Starting the app..."
|
||||
"$DEST" >/dev/null 2>&1 &
|
||||
74
installers/maturita-installer-macos.command
Executable file
74
installers/maturita-installer-macos.command
Executable file
|
|
@ -0,0 +1,74 @@
|
|||
#!/bin/sh
|
||||
# maturita.c installer for macOS.
|
||||
#
|
||||
# Carries no application of its own: it downloads whatever the newest release
|
||||
# is at the moment you run it, so this file never goes stale. GitHub resolves
|
||||
# the /releases/latest/download/ path to the current tag on every request.
|
||||
#
|
||||
# Double-click the file to run it. The app updates itself from then on.
|
||||
|
||||
set -eu
|
||||
|
||||
REPO="pepaskopec-blip/maturita.c"
|
||||
ASSET="maturita-macos-arm64.zip"
|
||||
URL="https://github.com/$REPO/releases/latest/download/$ASSET"
|
||||
|
||||
say() { printf '%s\n' "$*"; }
|
||||
die() { printf '\nError: %s\n' "$*" >&2; printf 'Press Return to close. '; read -r _; exit 1; }
|
||||
|
||||
say "Installing maturita.C"
|
||||
say "---------------------"
|
||||
|
||||
# Only Apple Silicon builds are published; Rosetta cannot run an arm64 app.
|
||||
arch=$(uname -m)
|
||||
if [ "$arch" != "arm64" ]; then
|
||||
die "this build is for Apple Silicon Macs, but this one reports '$arch'.
|
||||
Build from source instead: https://github.com/$REPO"
|
||||
fi
|
||||
|
||||
command -v curl >/dev/null 2>&1 || die "curl was not found."
|
||||
|
||||
# Prefer the shared folder, fall back to the user's own when it is locked down.
|
||||
if [ -w /Applications ]; then
|
||||
dest_dir="/Applications"
|
||||
else
|
||||
dest_dir="$HOME/Applications"
|
||||
mkdir -p "$dest_dir"
|
||||
fi
|
||||
|
||||
tmp=$(mktemp -d)
|
||||
trap 'rm -rf "$tmp"' EXIT INT TERM
|
||||
|
||||
say "Downloading the latest release..."
|
||||
curl -fL --progress-bar -o "$tmp/$ASSET" "$URL" ||
|
||||
die "the download failed. Check your internet connection."
|
||||
|
||||
say "Unpacking..."
|
||||
mkdir -p "$tmp/new"
|
||||
# ditto keeps bundle symlinks and permissions intact, unlike plain unzip.
|
||||
ditto -x -k "$tmp/$ASSET" "$tmp/new" || die "the archive could not be unpacked."
|
||||
|
||||
app=$(find "$tmp/new" -maxdepth 1 -name '*.app' -print -quit)
|
||||
[ -n "$app" ] || die "the archive did not contain an application."
|
||||
name=$(basename "$app")
|
||||
|
||||
say "Installing to $dest_dir/$name"
|
||||
rm -rf "$dest_dir/$name.old"
|
||||
if [ -e "$dest_dir/$name" ]; then
|
||||
mv "$dest_dir/$name" "$dest_dir/$name.old"
|
||||
fi
|
||||
if mv "$app" "$dest_dir/$name"; then
|
||||
rm -rf "$dest_dir/$name.old"
|
||||
else
|
||||
# Put the previous copy back rather than leaving nothing installed.
|
||||
[ -e "$dest_dir/$name.old" ] && mv "$dest_dir/$name.old" "$dest_dir/$name"
|
||||
die "could not write to $dest_dir."
|
||||
fi
|
||||
|
||||
# The download carries a quarantine flag, and the app is not signed, so
|
||||
# without this macOS refuses to open it.
|
||||
xattr -cr "$dest_dir/$name" 2>/dev/null || true
|
||||
|
||||
say ""
|
||||
say "Done. Starting the app..."
|
||||
open "$dest_dir/$name"
|
||||
80
installers/maturita-installer-windows.cmd
Normal file
80
installers/maturita-installer-windows.cmd
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
@echo off
|
||||
rem maturita.c installer for Windows.
|
||||
rem
|
||||
rem Carries no application of its own: it downloads whatever the newest release
|
||||
rem is at the moment you run it, so this file never goes stale. GitHub resolves
|
||||
rem the /releases/latest/download/ path to the current tag on every request.
|
||||
rem
|
||||
rem Double-click the file to run it. The app updates itself from then on.
|
||||
|
||||
setlocal
|
||||
set "REPO=pepaskopec-blip/maturita.c"
|
||||
set "ASSET=maturita-windows-x64.zip"
|
||||
set "URL=https://github.com/%REPO%/releases/latest/download/%ASSET%"
|
||||
set "DEST=%LOCALAPPDATA%\Programs\Maturita"
|
||||
|
||||
echo Installing maturita.C
|
||||
echo ---------------------
|
||||
|
||||
rem curl and tar both ship with Windows 10 1803 and later.
|
||||
where curl >nul 2>&1 || goto :no_tools
|
||||
where tar >nul 2>&1 || goto :no_tools
|
||||
|
||||
set "TMP_DIR=%TEMP%\maturita-installer"
|
||||
rmdir /s /q "%TMP_DIR%" 2>nul
|
||||
mkdir "%TMP_DIR%" || goto :fail_tmp
|
||||
|
||||
echo Downloading the latest release...
|
||||
curl -fL --progress-bar -o "%TMP_DIR%\%ASSET%" "%URL%" || goto :fail_download
|
||||
|
||||
echo Installing to %DEST%
|
||||
if not exist "%DEST%" mkdir "%DEST%" || goto :fail_dest
|
||||
|
||||
rem Extracted over any existing install rather than replacing the folder, so
|
||||
rem the progress files kept inside it survive an upgrade.
|
||||
tar -xf "%TMP_DIR%\%ASSET%" -C "%DEST%" || goto :fail_extract
|
||||
|
||||
rem Start menu entry, so the app can be found without digging for the folder.
|
||||
set "LNK=%APPDATA%\Microsoft\Windows\Start Menu\Programs\maturita.C.lnk"
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -Command ^
|
||||
"$s=(New-Object -ComObject WScript.Shell).CreateShortcut('%LNK%');" ^
|
||||
"$s.TargetPath='%DEST%\maturita.exe';$s.WorkingDirectory='%DEST%';$s.Save()" >nul 2>&1
|
||||
|
||||
rmdir /s /q "%TMP_DIR%" 2>nul
|
||||
|
||||
echo.
|
||||
echo Done. Starting the app...
|
||||
start "" "%DEST%\maturita.exe"
|
||||
exit /b 0
|
||||
|
||||
:no_tools
|
||||
echo.
|
||||
echo Error: this installer needs curl and tar, which come with Windows 10
|
||||
echo version 1803 and later. Please update Windows, or download the zip
|
||||
echo manually from https://github.com/%REPO%/releases/latest
|
||||
pause
|
||||
exit /b 1
|
||||
|
||||
:fail_tmp
|
||||
echo.
|
||||
echo Error: could not create a temporary folder in %TEMP%.
|
||||
pause
|
||||
exit /b 1
|
||||
|
||||
:fail_download
|
||||
echo.
|
||||
echo Error: the download failed. Check your internet connection.
|
||||
pause
|
||||
exit /b 1
|
||||
|
||||
:fail_dest
|
||||
echo.
|
||||
echo Error: could not create %DEST%.
|
||||
pause
|
||||
exit /b 1
|
||||
|
||||
:fail_extract
|
||||
echo.
|
||||
echo Error: the archive could not be unpacked.
|
||||
pause
|
||||
exit /b 1
|
||||
Loading…
Add table
Add a link
Reference in a new issue