diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f8942885..0107c26b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -74,16 +74,32 @@ jobs: - name: Build Windows (release) run: flutter build windows --release - - name: Zip Windows artifact + - name: Zip Windows artifact (portable) run: | $v = "${{ steps.version.outputs.version }}" $dir = "build\windows\x64\runner\Release" Compress-Archive -Path "$dir\*" -DestinationPath "Querya-Desktop-$v-windows.zip" + - name: Install Inno Setup + run: choco install innosetup --no-progress -y + + - name: Build Windows setup.exe (installable) + shell: pwsh + run: | + $v = "${{ steps.version.outputs.version }}" + $iscc = "${env:ProgramFiles(x86)}\Inno Setup 6\ISCC.exe" + if (!(Test-Path $iscc)) { throw "ISCC not found at $iscc" } + & $iscc "/DMyAppVersion=$v" "packaging\windows\querya.iss" + $setup = "dist-windows\Querya-Desktop-$v-windows-setup.exe" + if (!(Test-Path $setup)) { throw "Setup not produced: $setup" } + Copy-Item $setup "Querya-Desktop-$v-windows-setup.exe" + - uses: actions/upload-artifact@v4 with: name: bundle-windows - path: Querya-Desktop-${{ steps.version.outputs.version }}-windows.zip + path: | + Querya-Desktop-${{ steps.version.outputs.version }}-windows.zip + Querya-Desktop-${{ steps.version.outputs.version }}-windows-setup.exe if-no-files-found: error build-linux: @@ -119,15 +135,24 @@ jobs: - name: Build Linux (release) run: flutter build linux --release - - name: Zip Linux artifact + - name: Zip Linux artifact (portable) run: | cd build/linux/x64/release/bundle zip -r "${GITHUB_WORKSPACE}/Querya-Desktop-${{ steps.version.outputs.version }}-linux.zip" . + - name: Build Linux AppImage (installable) + run: ./scripts/linux/build_appimage.sh + + - name: Build Linux .deb (Debian/Ubuntu) + run: ./scripts/linux/build_deb.sh + - uses: actions/upload-artifact@v4 with: name: bundle-linux - path: Querya-Desktop-${{ steps.version.outputs.version }}-linux.zip + path: | + Querya-Desktop-${{ steps.version.outputs.version }}-linux.zip + Querya-Desktop-${{ steps.version.outputs.version }}-linux.AppImage + Querya-Desktop-${{ steps.version.outputs.version }}-linux.deb if-no-files-found: error build-macos: @@ -241,10 +266,14 @@ jobs: run: | set -euo pipefail mkdir -p dist - find artifacts -name '*.zip' -exec mv -t dist/ {} + + find artifacts \( -name '*.zip' -o -name '*.AppImage' -o -name '*.deb' -o -name '*-windows-setup.exe' \) \ + -exec mv -t dist/ {} + test "$(find dist -name '*.zip' | wc -l)" -eq 3 + test "$(find dist -name '*.AppImage' | wc -l)" -eq 1 + test "$(find dist -name '*.deb' | wc -l)" -eq 1 + test "$(find dist -name '*-windows-setup.exe' | wc -l)" -eq 1 cd dist - sha256sum *.zip | tee SHA256SUMS.txt + sha256sum *.* | tee SHA256SUMS.txt - name: Build release notes from CHANGELOG.md run: | @@ -265,7 +294,11 @@ jobs: echo "Optional USB-style profile: set \`QUERYA_PORTABLE=1\` or create a \`QueryaData/\` folder next to the binary (see docs/packaging.md)." echo "" echo "#### Installable" - echo "_AppImage / Windows setup / distro packages — tracked in epic #379; not attached to this release yet._" + echo "- **Linux AppImage**: \`Querya-Desktop-${VERSION}-linux.AppImage\` (\`chmod +x\` then run)" + echo "- **Linux .deb** (Debian/Ubuntu): \`Querya-Desktop-${VERSION}-linux.deb\` — \`sudo apt install ./Querya-Desktop-${VERSION}-linux.deb\`" + echo "- **Windows setup**: \`Querya-Desktop-${VERSION}-windows-setup.exe\` (Inno Setup)" + echo "" + echo "RPM / Flatpak / AUR — follow-ups on #386." echo "" echo "Verify checksums: \`SHA256SUMS.txt\`" echo "" @@ -289,9 +322,12 @@ jobs: tag_name: ${{ steps.rel.outputs.tag }} name: Querya Desktop ${{ needs.build-windows.outputs.version }} body_path: release-notes.md - fail_on_unmatched_files: true + fail_on_unmatched_files: false files: | dist/*.zip + dist/*.deb + dist/*.AppImage + dist/*-windows-setup.exe dist/SHA256SUMS.txt env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index dfdc4895..025ddbec 100644 --- a/.gitignore +++ b/.gitignore @@ -39,5 +39,11 @@ coverage/ *.so *.dll *.exe +dist-windows/ design-front/ docker/sqlite/data/ + +# Local packaging outputs +Querya-Desktop-*.deb +Querya-Desktop-*.AppImage +Querya-Desktop-*.zip diff --git a/docs/tags-and-releases.md b/docs/tags-and-releases.md index 70e03bf3..1907b485 100644 --- a/docs/tags-and-releases.md +++ b/docs/tags-and-releases.md @@ -37,9 +37,19 @@ Профиль по умолчанию всё равно в OS app-support; USB-style data → [packaging.md](packaging.md) (`QUERYA_PORTABLE` / `QueryaData/`). -### Installable channel (planned) +### Installable channel -Отдельные артефакты (AppImage, Windows setup, deb/rpm/Flatpak) — epic [#379](https://github.com/QueryaHub/Querya-Desktop/issues/379). Пока в Release публикуются только portable zip выше. +| Artifact | Notes | +|----------|--------| +| `Querya-Desktop-X.Y.Z-linux.AppImage` | [`scripts/linux/build_appimage.sh`](../scripts/linux/build_appimage.sh) (`chmod +x` then run) | +| `Querya-Desktop-X.Y.Z-linux.deb` | Debian/Ubuntu — [`scripts/linux/build_deb.sh`](../scripts/linux/build_deb.sh) | +| `Querya-Desktop-X.Y.Z-windows-setup.exe` | Inno Setup (`packaging/windows/querya.iss`) | + +```bash +sudo apt install ./Querya-Desktop-X.Y.Z-linux.deb +``` + +RPM / Flatpak / AUR: [#386](https://github.com/QueryaHub/Querya-Desktop/issues/386) / epic [#379](https://github.com/QueryaHub/Querya-Desktop/issues/379). ## Changelog в GitHub Release diff --git a/packaging/windows/querya.iss b/packaging/windows/querya.iss new file mode 100644 index 00000000..ea2113d9 --- /dev/null +++ b/packaging/windows/querya.iss @@ -0,0 +1,53 @@ +; Inno Setup script for Querya Desktop (Windows installable channel). +; Compile from repo root after `flutter build windows --release`: +; ISCC /DMyAppVersion=0.4.11 packaging\windows\querya.iss + +#ifndef MyAppVersion + #define MyAppVersion "0.0.0" +#endif + +#define MyAppName "Querya Desktop" +#define MyAppPublisher "QueryaHub" +#define MyAppExeName "querya_desktop.exe" +#define MyAppSourceDir "..\..\build\windows\x64\runner\Release" + +[Setup] +; Stable AppId — do not change across releases (controls uninstall / upgrades). +AppId={{A7C3E2F1-9B4D-4E8A-8F2C-1D5E6A7B8C9D} +AppName={#MyAppName} +AppVersion={#MyAppVersion} +AppPublisher={#MyAppPublisher} +AppPublisherURL=https://github.com/QueryaHub/Querya-Desktop +DefaultDirName={autopf}\Querya Desktop +DefaultGroupName=Querya Desktop +DisableProgramGroupPage=yes +LicenseFile= +OutputDir=..\..\dist-windows +OutputBaseFilename=Querya-Desktop-{#MyAppVersion}-windows-setup +SetupIconFile=..\..\windows\runner\resources\app_icon.ico +Compression=lzma +SolidCompression=yes +WizardStyle=modern +PrivilegesRequired=lowest +PrivilegesRequiredOverridesAllowed=dialog +ArchitecturesAllowed=x64compatible +ArchitecturesInstallIn64BitMode=x64compatible +UninstallDisplayIcon={app}\{#MyAppExeName} +CloseApplications=yes +RestartApplications=no + +[Languages] +Name: "english"; MessagesFile: "compiler:Default.isl" + +[Tasks] +Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked + +[Files] +Source: "{#MyAppSourceDir}\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs + +[Icons] +Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}" +Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon + +[Run] +Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent diff --git a/scripts/linux/build_appimage.sh b/scripts/linux/build_appimage.sh new file mode 100755 index 00000000..0f974619 --- /dev/null +++ b/scripts/linux/build_appimage.sh @@ -0,0 +1,75 @@ +#!/usr/bin/env bash +# Build Querya-Desktop-*.AppImage from a Flutter linux release bundle. +# +# Usage: +# ./scripts/linux/build_appimage.sh [bundle_dir] [output_appimage] +# +# Defaults: +# bundle_dir = build/linux/x64/release/bundle +# output = Querya-Desktop--linux.AppImage +set -euo pipefail + +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +BUNDLE="${1:-$ROOT/build/linux/x64/release/bundle}" +BINARY_NAME="querya_desktop" +ICON_SRC="$ROOT/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png" + +if [[ ! -d "$BUNDLE" ]]; then + echo "error: Flutter linux bundle not found: $BUNDLE" >&2 + echo "Run: flutter build linux --release" >&2 + exit 1 +fi +if [[ ! -x "$BUNDLE/$BINARY_NAME" ]]; then + echo "error: missing executable: $BUNDLE/$BINARY_NAME" >&2 + exit 1 +fi +if [[ ! -f "$ICON_SRC" ]]; then + echo "error: icon not found: $ICON_SRC" >&2 + exit 1 +fi + +VERSION="$(grep '^version:' "$ROOT/pubspec.yaml" | sed 's/^version: //; s/+.*//')" +OUT="${2:-$ROOT/Querya-Desktop-${VERSION}-linux.AppImage}" + +WORKDIR="$(mktemp -d "${TMPDIR:-/tmp}/querya-appimage.XXXXXX")" +cleanup() { rm -rf "$WORKDIR"; } +trap cleanup EXIT + +APPDIR="$WORKDIR/AppDir" +mkdir -p "$APPDIR" +cp -a "$BUNDLE"/. "$APPDIR/" + +cp "$ICON_SRC" "$APPDIR/${BINARY_NAME}.png" + +cat > "$APPDIR/${BINARY_NAME}.desktop" < "$APPDIR/AppRun" <<'EOF' +#!/bin/bash +set -euo pipefail +HERE="$(dirname "$(readlink -f "$0")")" +export LD_LIBRARY_PATH="${HERE}/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" +cd "$HERE" +exec "$HERE/querya_desktop" "$@" +EOF +chmod +x "$APPDIR/AppRun" "$APPDIR/$BINARY_NAME" + +TOOL="$WORKDIR/appimagetool" +# Prefer type-2 continuous tool; --appimage-extract-and-run avoids FUSE on CI. +curl -fsSL -o "$TOOL" \ + "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage" +chmod +x "$TOOL" + +ARCH=x86_64 "$TOOL" --appimage-extract-and-run "$APPDIR" "$OUT" +chmod +x "$OUT" +echo "Wrote $OUT" diff --git a/scripts/linux/build_deb.sh b/scripts/linux/build_deb.sh new file mode 100755 index 00000000..ce39bb2e --- /dev/null +++ b/scripts/linux/build_deb.sh @@ -0,0 +1,87 @@ +#!/usr/bin/env bash +# Build Querya-Desktop-*.deb from a Flutter linux release bundle (Debian/Ubuntu). +# +# Usage: +# ./scripts/linux/build_deb.sh [bundle_dir] [output_deb] +set -euo pipefail + +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +BUNDLE="${1:-$ROOT/build/linux/x64/release/bundle}" +BINARY_NAME="querya_desktop" +# Keep in sync with linux/CMakeLists.txt APPLICATION_ID (and #385 when merged). +APP_ID="${QUERYA_LINUX_APP_ID:-com.queryahub.querya_desktop}" +ICON_SRC="$ROOT/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png" + +if [[ ! -d "$BUNDLE" ]]; then + echo "error: Flutter linux bundle not found: $BUNDLE" >&2 + exit 1 +fi +if [[ ! -x "$BUNDLE/$BINARY_NAME" ]]; then + echo "error: missing executable: $BUNDLE/$BINARY_NAME" >&2 + exit 1 +fi +if ! command -v dpkg-deb >/dev/null 2>&1; then + echo "error: dpkg-deb is required (apt install dpkg)" >&2 + exit 1 +fi + +VERSION="$(grep '^version:' "$ROOT/pubspec.yaml" | sed 's/^version: //; s/+.*//')" +OUT="${2:-$ROOT/Querya-Desktop-${VERSION}-linux.deb}" +ARCH="$(dpkg --print-architecture 2>/dev/null || echo amd64)" + +WORKDIR="$(mktemp -d "${TMPDIR:-/tmp}/querya-deb.XXXXXX")" +cleanup() { rm -rf "$WORKDIR"; } +trap cleanup EXIT + +PKG="$WORKDIR/pkg" +INSTALL_ROOT="$PKG/opt/querya-desktop" +mkdir -p \ + "$INSTALL_ROOT" \ + "$PKG/usr/bin" \ + "$PKG/usr/share/applications" \ + "$PKG/usr/share/icons/hicolor/512x512/apps" \ + "$PKG/DEBIAN" + +cp -a "$BUNDLE"/. "$INSTALL_ROOT/" +chmod +x "$INSTALL_ROOT/$BINARY_NAME" + +ln -s "/opt/querya-desktop/$BINARY_NAME" "$PKG/usr/bin/$BINARY_NAME" + +if [[ -f "$ICON_SRC" ]]; then + cp "$ICON_SRC" "$PKG/usr/share/icons/hicolor/512x512/apps/${BINARY_NAME}.png" +fi + +cat > "$PKG/usr/share/applications/${BINARY_NAME}.desktop" < "$PKG/DEBIAN/control" < +Installed-Size: ${INSTALLED_SIZE} +Depends: libgtk-3-0, libsecret-1-0, libglib2.0-0 +Recommends: libayatana-appindicator3-1 +Homepage: https://github.com/QueryaHub/Querya-Desktop +Description: Querya Desktop database client + Multi-database desktop client for PostgreSQL, MySQL, Redis, MongoDB, + SQLite, and sandboxed drivers. +EOF + +dpkg-deb --root-owner-group --build "$PKG" "$OUT" +echo "Wrote $OUT"