build: add portable desktop packages

This commit is contained in:
mirivlad 2026-07-13 22:29:58 +08:00
parent f4e911c14a
commit 20952e8477
20 changed files with 476 additions and 34 deletions

8
.gitignore vendored
View File

@ -2,7 +2,15 @@
frontend/node_modules/ frontend/node_modules/
frontend/dist/ frontend/dist/
build/bin/verstak-desktop build/bin/verstak-desktop
build/appicon.png
build/windows/
build/windows-amd64/ build/windows-amd64/
build/linux-amd64/
build/appimage/
build/deb/
build/downloads/
build/tools/
build/webview2-runtime/
smoke-platform smoke-platform
plugins/ plugins/
vendor/ vendor/

View File

@ -26,8 +26,7 @@ No server account or browser extension is needed for a local desktop vault.
## Build the desktop and official plugins ## Build the desktop and official plugins
The current release scripts target Linux. Install Go 1.24+, Node.js 20+ with To build from source, install Go 1.24+, Node.js 20+ with npm, Python 3, the [Wails v2 build
npm, Python 3, the [Wails v2 build
prerequisites](https://wails.io/docs/gettingstarted/installation/), and your prerequisites](https://wails.io/docs/gettingstarted/installation/), and your
distribution's WebKitGTK development package. distribution's WebKitGTK development package.
@ -78,29 +77,45 @@ diagnostic logs:
./build/bin/verstak-desktop --debug ./build/bin/verstak-desktop --debug
``` ```
## Windows test bundle from Linux ## Portable test artifacts
The current Windows path is intended for manual testing, not publication. On a These commands make local alpha artifacts in `release/`. They do not create a
Linux host install MinGW, then run: GitHub Release.
```bash ```bash
sudo apt install gcc-mingw-w64-x86-64 # Debian 13 / Ubuntu 24.04 or later. APT installs WebKitGTK dependencies.
./scripts/build-windows.sh ./scripts/package-deb.sh v0.1.0-alpha.1
# Portable Linux x86_64 AppImage with bundled WebKitGTK runtime and plugins.
./scripts/package-appimage.sh v0.1.0-alpha.1
``` ```
The script builds Windows amd64 plugin packages from the sibling Install the Debian package with `sudo apt install ./release/verstak_*.deb`,
`verstak-official-plugins` checkout, cross-compiles the Wails host, and writes then launch `verstak`. Run the AppImage directly after making it executable:
a folder ready to copy to a Windows machine:
```text ```bash
build/windows-amd64/ chmod +x release/verstak-linux-x86_64-v0.1.0-alpha.1.AppImage
├── verstak-desktop.exe ./release/verstak-linux-x86_64-v0.1.0-alpha.1.AppImage
└── plugins/
``` ```
Copy the whole directory to Windows and run `verstak-desktop.exe`. Windows On distributions without FUSE support, use
requires the Microsoft WebView2 Runtime; Windows 11 normally includes it. `APPIMAGE_EXTRACT_AND_RUN=1 ./release/verstak-linux-x86_64-v0.1.0-alpha.1.AppImage`.
No Windows GitHub Release is created by this command.
Build the Windows portable ZIP on Linux with MinGW:
```bash
sudo apt install gcc-mingw-w64-x86-64 cabextract zip
./scripts/package-windows-portable.sh v0.1.0-alpha.1
```
The script downloads the current x64 Microsoft Fixed Version WebView2 Runtime,
bundles it next to `verstak-desktop.exe`, and writes
`release/verstak-windows-amd64-<version>.zip`. On Windows, extract the ZIP to a
local disk (not a network share) and launch `Verstak.cmd`. No separate WebView2
installation or download is required. To make a reproducible build from an
already downloaded CAB, set `VERSTAK_WEBVIEW2_CAB=/path/to/FixedVersionRuntime.x64.cab`.
Each format is listed in `release/SHA256SUMS` after packaging.
## First local vault ## First local vault
@ -154,25 +169,26 @@ README](https://github.com/mirivlad/verstak-sync-server#readme). In the desktop
application, open the Sync plugin, enter the server URL and user credentials, application, open the Sync plugin, enter the server URL and user credentials,
test the connection, then select **Connect**. Each vault is paired separately. test the connection, then select **Connect**. Each vault is paired separately.
## Release artifacts ## Separate plugin archives
Maintainers can produce a self-contained Linux desktop archive after the SDK The desktop artifacts already include matching official plugins. To distribute
and official plugins have been built: plugins separately, build OS-specific archives in the sibling repository:
```bash ```bash
cd verstak cd ../verstak-official-plugins
./scripts/release.sh v0.1.0-alpha.1 sudo apt install gcc-mingw-w64-x86-64 zip
./scripts/package-portable.sh v0.1.0-alpha.1
``` ```
It writes `release/verstak-desktop-linux-amd64-<version>.tar.gz` and a matching It writes a Linux `tar.gz` and a Windows ZIP. Both archives expand directly
`SHA256SUMS` file. Unpack the archive and run the included executable; its into the `plugins/` directory beside the corresponding desktop executable.
matching plugins are already in the archive. The browser extension, SDK, Separate archives are required because `platform-test` includes a native
official plugins and sync server have their own build or release instructions sidecar for its target OS.
in their repositories.
## Publish a GitHub Release ## Publish a GitHub Release
After checking the local archive, publish the same assets to GitHub: The current publisher still uses the legacy Linux tarball. It will be switched
to the portable artifacts after they have been manually checked:
```bash ```bash
./scripts/publish-github-release.sh v0.1.0-alpha.1 ./scripts/publish-github-release.sh v0.1.0-alpha.1

View File

@ -243,7 +243,7 @@ func main() {
} }
// ─── Wails App ─────────────────────────────────────────── // ─── Wails App ───────────────────────────────────────────
err = wails.Run(&options.App{ appOptions := &options.App{
Title: "Verstak", Title: "Verstak",
Width: 1200, Width: 1200,
Height: 800, Height: 800,
@ -257,7 +257,9 @@ func main() {
Bind: []interface{}{ Bind: []interface{}{
app, app,
}, },
}) }
applyPlatformOptions(appOptions)
err = wails.Run(appOptions)
if err != nil { if err != nil {
log.Fatalf("Error: %v", err) log.Fatalf("Error: %v", err)

11
packaging/deb/control Normal file
View File

@ -0,0 +1,11 @@
Package: verstak
Version: @VERSION@
Section: utils
Priority: optional
Architecture: amd64
Depends: libwebkit2gtk-4.1-0, libgtk-3-0t64 | libgtk-3-0
Maintainer: Verstak contributors <dev@verstak.app>
Homepage: https://github.com/mirivlad/verstak
Description: Local-first workspace
Verstak is a local-first workspace for files, notes, browser captures,
activity and work-journal entries.

2
packaging/deb/verstak Executable file
View File

@ -0,0 +1,2 @@
#!/usr/bin/env sh
exec /opt/verstak/verstak-desktop "$@"

13
packaging/linux/AppRun Executable file
View File

@ -0,0 +1,13 @@
#!/usr/bin/env sh
set -eu
HERE="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)"
export APPDIR="$HERE"
export LD_LIBRARY_PATH="$HERE/usr/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
export GIO_EXTRA_MODULES="$HERE/usr/lib/gio/modules"
export GSETTINGS_SCHEMA_DIR="$HERE/usr/share/glib-2.0/schemas"
export GST_PLUGIN_SYSTEM_PATH_1_0="$HERE/usr/lib/gstreamer-1.0"
export WEBKIT_EXEC_PATH="$HERE/usr/lib/webkit2gtk-4.1"
cd "$HERE/usr/bin"
exec "$HERE/usr/bin/verstak-desktop" "$@"

View File

@ -0,0 +1,9 @@
[Desktop Entry]
Type=Application
Name=Verstak
Comment=Local-first workspace
Exec=verstak-desktop %U
Icon=verstak
Terminal=false
Categories=Office;Utility;
StartupNotify=true

View File

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128">
<rect width="128" height="128" rx="26" fill="#1c2f4a"/>
<path d="M28 34h72v18H28zm0 31h72v29H28z" fill="#72d2b3"/>
<path d="M41 52v13m23-13v13m23-13v13" stroke="#1c2f4a" stroke-width="8"/>
</svg>

After

Width:  |  Height:  |  Size: 290 B

View File

@ -0,0 +1,13 @@
@echo off
setlocal
set "ROOT=%~dp0"
if not exist "%ROOT%webview2\msedgewebview2.exe" (
echo The bundled WebView2 runtime is missing.
pause
exit /b 1
)
icacls "%ROOT%webview2" /grant *S-1-15-2-2:(OI)(CI)(RX) /T /C >nul 2>&1
icacls "%ROOT%webview2" /grant *S-1-15-2-1:(OI)(CI)(RX) /T /C >nul 2>&1
start "" "%ROOT%verstak-desktop.exe" %*

View File

@ -0,0 +1,7 @@
//go:build !windows
package main
import "github.com/wailsapp/wails/v2/pkg/options"
func applyPlatformOptions(_ *options.App) {}

View File

@ -0,0 +1,35 @@
//go:build windows
package main
import (
"os"
"os/exec"
"path/filepath"
"github.com/wailsapp/wails/v2/pkg/options"
"github.com/wailsapp/wails/v2/pkg/options/windows"
)
func applyPlatformOptions(app *options.App) {
executablePath, err := os.Executable()
if err != nil {
return
}
runtimePath := bundledWebView2Path(executablePath)
if _, err := os.Stat(filepath.Join(runtimePath, "msedgewebview2.exe")); err != nil {
return
}
// Fixed Version WebView2 runtimes from v120 need these permissions on
// unpackaged Windows 10 applications. The archive is extracted by the user,
// so the command can update permissions without an installer or download.
for _, sid := range []string{"*S-1-15-2-2", "*S-1-15-2-1"} {
_ = exec.Command("icacls", runtimePath, "/grant", sid+":(OI)(CI)(RX)", "/T", "/C").Run()
}
app.Windows = &windows.Options{
WebviewBrowserPath: runtimePath,
}
}

7
runtime_path.go Normal file
View File

@ -0,0 +1,7 @@
package main
import "path/filepath"
func bundledWebView2Path(executablePath string) string {
return filepath.Join(filepath.Dir(executablePath), "webview2")
}

11
runtime_path_test.go Normal file
View File

@ -0,0 +1,11 @@
package main
import "testing"
func TestBundledWebView2PathUsesExecutableDirectory(t *testing.T) {
got := bundledWebView2Path("/opt/verstak/verstak-desktop")
want := "/opt/verstak/webview2"
if got != want {
t.Fatalf("bundledWebView2Path() = %q, want %q", got, want)
}
}

31
scripts/build-linux-bundle.sh Executable file
View File

@ -0,0 +1,31 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
OFFICIAL_PLUGINS="${VERSTAK_OFFICIAL_PLUGINS_DIR:-$ROOT/../verstak-official-plugins}"
OUTPUT="${VERSTAK_LINUX_BUNDLE_DIR:-$ROOT/build/linux-amd64}"
if [[ ! -d "$OFFICIAL_PLUGINS" ]]; then
echo "official plugins repository not found: $OFFICIAL_PLUGINS" >&2
exit 1
fi
echo "=== verstak desktop Linux amd64 bundle ==="
(cd "$OFFICIAL_PLUGINS" && ./scripts/build.sh)
"$ROOT/scripts/install-dev-plugins.sh"
"$ROOT/scripts/build.sh"
BINARY="$ROOT/build/bin/verstak-desktop"
if [[ ! -x "$BINARY" ]]; then
echo "desktop binary was not produced: $BINARY" >&2
exit 1
fi
rm -rf "$OUTPUT"
mkdir -p "$OUTPUT"
install -m 755 "$BINARY" "$OUTPUT/verstak-desktop"
install -m 644 "$ROOT/README.md" "$ROOT/LICENSE" "$OUTPUT/"
cp -R "$ROOT/plugins" "$OUTPUT/plugins"
chmod -R a+rX "$OUTPUT/plugins"
echo "Linux bundle: $OUTPUT"

View File

@ -53,9 +53,12 @@ if [[ ! -d "$WINDOWS_PLUGIN_DIST" ]]; then
exit 1 exit 1
fi fi
# Wails generates Windows resources and invokes the supplied MinGW compiler. # Wails' -compiler option selects a Go binary, not a C compiler. Cross-CGO
# -clean resets build/bin, so copy the finished executable only afterwards. # therefore has to be supplied through the standard Go environment instead.
"$WAILS" build -clean -platform windows/amd64 -compiler "$WINDOWS_CC" -o verstak-desktop.exe # The runtime is bundled by package-windows-portable.sh, so never compile an
# Evergreen downloader into the portable executable.
CC="$WINDOWS_CC" CGO_ENABLED=1 "$WAILS" build -clean -platform windows/amd64 \
-webview2 error -o verstak-desktop.exe
WINDOWS_BINARY="$ROOT/build/bin/verstak-desktop.exe" WINDOWS_BINARY="$ROOT/build/bin/verstak-desktop.exe"
if [[ ! -f "$WINDOWS_BINARY" ]]; then if [[ ! -f "$WINDOWS_BINARY" ]]; then

118
scripts/package-appimage.sh Executable file
View File

@ -0,0 +1,118 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
VERSION="${1:-}"
APPIMAGETOOL_URL="${APPIMAGETOOL_URL:-https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage}"
if [[ -z "$VERSION" || ! "$VERSION" =~ ^[A-Za-z0-9][A-Za-z0-9._-]*$ ]]; then
echo "usage: $0 <version>" >&2
echo "example: $0 v0.1.0-alpha.1" >&2
exit 2
fi
if ! command -v ldd >/dev/null || ! command -v file >/dev/null; then
echo "ldd and file are required to bundle AppImage runtime libraries" >&2
exit 1
fi
"$ROOT/scripts/build-linux-bundle.sh"
APPIMAGETOOL="${APPIMAGETOOL_BIN:-$ROOT/build/tools/appimagetool-x86_64.AppImage}"
if [[ ! -x "$APPIMAGETOOL" ]]; then
if ! command -v curl >/dev/null; then
echo "appimagetool is missing; install curl or set APPIMAGETOOL_BIN" >&2
exit 1
fi
mkdir -p "$(dirname "$APPIMAGETOOL")"
curl --fail --location --show-error "$APPIMAGETOOL_URL" -o "$APPIMAGETOOL"
chmod +x "$APPIMAGETOOL"
fi
BUNDLE="${VERSTAK_LINUX_BUNDLE_DIR:-$ROOT/build/linux-amd64}"
APPDIR="$ROOT/build/appimage/AppDir"
RELEASE_ROOT="$ROOT/release"
ARCHIVE="$RELEASE_ROOT/verstak-linux-x86_64-$VERSION.AppImage"
WEBKIT_RUNTIME_DIR="${VERSTAK_WEBKIT_RUNTIME_DIR:-/usr/lib/x86_64-linux-gnu/webkit2gtk-4.1}"
if [[ ! -d "$WEBKIT_RUNTIME_DIR" ]] || [[ ! -x "$WEBKIT_RUNTIME_DIR/WebKitWebProcess" ]]; then
echo "WebKitWebProcess was not found at $WEBKIT_RUNTIME_DIR" >&2
echo "Set VERSTAK_WEBKIT_RUNTIME_DIR to the WebKitGTK 4.1 runtime directory." >&2
exit 1
fi
rm -rf "$APPDIR" "$ARCHIVE"
mkdir -p "$APPDIR/usr/bin" "$APPDIR/usr/lib" "$APPDIR/usr/share/applications" \
"$APPDIR/usr/share/icons/hicolor/scalable/apps"
install -m 755 "$ROOT/packaging/linux/AppRun" "$APPDIR/AppRun"
install -m 755 "$BUNDLE/verstak-desktop" "$APPDIR/usr/bin/verstak-desktop"
install -m 644 "$ROOT/packaging/linux/verstak.desktop" "$APPDIR/verstak.desktop"
install -m 644 "$ROOT/packaging/linux/verstak.desktop" "$APPDIR/usr/share/applications/verstak.desktop"
install -m 644 "$ROOT/packaging/linux/verstak.svg" "$APPDIR/verstak.svg"
install -m 644 "$ROOT/packaging/linux/verstak.svg" "$APPDIR/usr/share/icons/hicolor/scalable/apps/verstak.svg"
cp -R "$BUNDLE/plugins" "$APPDIR/usr/bin/plugins"
cp -a "$WEBKIT_RUNTIME_DIR" "$APPDIR/usr/lib/webkit2gtk-4.1"
copy_runtime_dir() {
local source="$1"
local target="$2"
if [[ -d "$source" ]]; then
mkdir -p "$target"
cp -a "$source/." "$target/"
fi
}
copy_runtime_dir /usr/lib/x86_64-linux-gnu/gio/modules "$APPDIR/usr/lib/gio/modules"
copy_runtime_dir /usr/lib/x86_64-linux-gnu/gstreamer-1.0 "$APPDIR/usr/lib/gstreamer-1.0"
copy_runtime_dir /usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0 "$APPDIR/usr/lib/gdk-pixbuf-2.0"
copy_runtime_dir /usr/share/glib-2.0/schemas "$APPDIR/usr/share/glib-2.0/schemas"
declare -A queued=()
queue_elf() {
local candidate="$1"
[[ -f "$candidate" ]] || return
if [[ "$(file --brief "$candidate")" != *ELF* ]]; then
return
fi
if [[ -z "${queued[$candidate]:-}" ]]; then
queued[$candidate]=1
printf '%s\n' "$candidate" >> "$APPDIR/.elf-queue"
fi
}
queue_elf "$APPDIR/usr/bin/verstak-desktop"
while IFS= read -r candidate; do
queue_elf "$candidate"
done < <(find "$APPDIR/usr/lib/webkit2gtk-4.1" "$APPDIR/usr/lib/gio/modules" \
"$APPDIR/usr/lib/gstreamer-1.0" "$APPDIR/usr/lib/gdk-pixbuf-2.0" -type f)
while IFS= read -r candidate; do
if ldd "$candidate" | grep -q 'not found'; then
echo "unresolved shared library in $candidate" >&2
exit 1
fi
while IFS= read -r library; do
case "$(basename "$library")" in
libc.so.6|libm.so.6|libpthread.so.0|librt.so.1|libdl.so.2|ld-linux-x86-64.so.2)
continue
;;
esac
bundled="$APPDIR/usr/lib/$(basename "$library")"
if [[ ! -e "$bundled" ]]; then
cp -aL "$library" "$bundled"
fi
queue_elf "$bundled"
done < <(ldd "$candidate" | awk '/=> \/[^ ]+/ { print $3 } /^\// { print $1 }')
done < "$APPDIR/.elf-queue"
rm -f "$APPDIR/.elf-queue"
if command -v glib-compile-schemas >/dev/null; then
glib-compile-schemas "$APPDIR/usr/share/glib-2.0/schemas"
fi
mkdir -p "$RELEASE_ROOT"
ARCH=x86_64 APPIMAGE_EXTRACT_AND_RUN=1 "$APPIMAGETOOL" "$APPDIR" "$ARCHIVE"
(cd "$RELEASE_ROOT" && find . -maxdepth 1 -type f \( -name '*.deb' -o -name '*.AppImage' -o -name '*.zip' \) \
-printf '%f\n' | LC_ALL=C sort | xargs -r sha256sum > SHA256SUMS)
echo "AppImage: $ARCHIVE"
echo "checksums: $RELEASE_ROOT/SHA256SUMS"

44
scripts/package-deb.sh Executable file
View File

@ -0,0 +1,44 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
VERSION="${1:-}"
if [[ -z "$VERSION" || ! "$VERSION" =~ ^[A-Za-z0-9][A-Za-z0-9._-]*$ ]]; then
echo "usage: $0 <version>" >&2
echo "example: $0 v0.1.0-alpha.1" >&2
exit 2
fi
if ! command -v dpkg-deb >/dev/null; then
echo "dpkg-deb is required to create a Debian package" >&2
exit 1
fi
"$ROOT/scripts/build-linux-bundle.sh"
PACKAGE_VERSION="${VERSION#v}"
BUNDLE="${VERSTAK_LINUX_BUNDLE_DIR:-$ROOT/build/linux-amd64}"
STAGING="$ROOT/build/deb/verstak_$PACKAGE_VERSION"
RELEASE_ROOT="$ROOT/release"
ARCHIVE="$RELEASE_ROOT/verstak_${PACKAGE_VERSION}_amd64.deb"
rm -rf "$STAGING" "$ARCHIVE"
mkdir -p "$STAGING/DEBIAN" "$STAGING/opt/verstak" "$STAGING/usr/bin" \
"$STAGING/usr/share/applications" "$STAGING/usr/share/icons/hicolor/scalable/apps" \
"$STAGING/usr/share/doc/verstak"
sed "s/@VERSION@/$PACKAGE_VERSION/g" "$ROOT/packaging/deb/control" > "$STAGING/DEBIAN/control"
install -m 755 "$ROOT/packaging/deb/verstak" "$STAGING/usr/bin/verstak"
install -m 755 "$BUNDLE/verstak-desktop" "$STAGING/opt/verstak/verstak-desktop"
install -m 644 "$BUNDLE/README.md" "$BUNDLE/LICENSE" "$STAGING/usr/share/doc/verstak/"
install -m 644 "$ROOT/packaging/linux/verstak.desktop" "$STAGING/usr/share/applications/verstak.desktop"
install -m 644 "$ROOT/packaging/linux/verstak.svg" "$STAGING/usr/share/icons/hicolor/scalable/apps/verstak.svg"
cp -R "$BUNDLE/plugins" "$STAGING/opt/verstak/plugins"
mkdir -p "$RELEASE_ROOT"
dpkg-deb --root-owner-group --build "$STAGING" "$ARCHIVE"
(cd "$RELEASE_ROOT" && find . -maxdepth 1 -type f \( -name '*.deb' -o -name '*.AppImage' -o -name '*.zip' \) \
-printf '%f\n' | LC_ALL=C sort | xargs -r sha256sum > SHA256SUMS)
echo "Debian package: $ARCHIVE"
echo "checksums: $RELEASE_ROOT/SHA256SUMS"

View File

@ -0,0 +1,77 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
VERSION="${1:-}"
WEBVIEW2_CAB="${VERSTAK_WEBVIEW2_CAB:-}"
WEBVIEW2_URL="${VERSTAK_WEBVIEW2_URL:-}"
if [[ -z "$VERSION" || ! "$VERSION" =~ ^[A-Za-z0-9][A-Za-z0-9._-]*$ ]]; then
echo "usage: $0 <version>" >&2
echo "example: $0 v0.1.0-alpha.1" >&2
exit 2
fi
for command in cabextract curl python3 zip; do
if ! command -v "$command" >/dev/null; then
echo "$command is required to create the Windows portable archive" >&2
exit 1
fi
done
if [[ -z "$WEBVIEW2_CAB" ]]; then
if [[ -z "$WEBVIEW2_URL" ]]; then
WEBVIEW2_URL="$(python3 - <<'PY'
import re
import sys
import urllib.request
with urllib.request.urlopen('https://developer.microsoft.com/en-us/microsoft-edge/webview2/', timeout=30) as response:
page = response.read().decode('utf-8')
page = page.replace(r'\u002F', '/')
match = re.search(r'"x64","(https://[^\"]+Microsoft\.WebView2\.FixedVersionRuntime[^\"]+\.x64\.cab)"', page)
if not match:
sys.exit('could not locate the x64 FixedVersionRuntime CAB on the Microsoft WebView2 download page')
print(match.group(1))
PY
)"
fi
WEBVIEW2_CAB="$ROOT/build/downloads/$(basename "${WEBVIEW2_URL%%\?*}")"
mkdir -p "$(dirname "$WEBVIEW2_CAB")"
if [[ ! -f "$WEBVIEW2_CAB" ]]; then
curl --fail --location --show-error "$WEBVIEW2_URL" -o "$WEBVIEW2_CAB"
fi
fi
if [[ ! -f "$WEBVIEW2_CAB" ]]; then
echo "FixedVersionRuntime CAB was not found: $WEBVIEW2_CAB" >&2
exit 1
fi
"$ROOT/scripts/build-windows.sh"
RUNTIME_EXTRACT="$ROOT/build/webview2-runtime"
rm -rf "$RUNTIME_EXTRACT"
mkdir -p "$RUNTIME_EXTRACT"
cabextract -q -d "$RUNTIME_EXTRACT" "$WEBVIEW2_CAB"
WEBVIEW2_RUNTIME_DIR="$(dirname "$(find "$RUNTIME_EXTRACT" -type f -iname msedgewebview2.exe -print -quit)")"
if [[ -z "$WEBVIEW2_RUNTIME_DIR" || ! -f "$WEBVIEW2_RUNTIME_DIR/msedgewebview2.exe" ]]; then
echo "FixedVersionRuntime CAB does not contain msedgewebview2.exe" >&2
exit 1
fi
RELEASE_ROOT="$ROOT/release"
STAGING="$RELEASE_ROOT/verstak-windows-amd64-$VERSION"
ARCHIVE="$RELEASE_ROOT/verstak-windows-amd64-$VERSION.zip"
rm -rf "$STAGING" "$ARCHIVE"
mkdir -p "$STAGING"
cp -R "$ROOT/build/windows-amd64/." "$STAGING/"
install -m 644 "$ROOT/README.md" "$ROOT/LICENSE" "$STAGING/"
install -m 644 "$ROOT/packaging/windows/Verstak.cmd" "$STAGING/Verstak.cmd"
cp -R "$WEBVIEW2_RUNTIME_DIR" "$STAGING/webview2"
(cd "$RELEASE_ROOT" && zip -qr "$(basename "$ARCHIVE")" "$(basename "$STAGING")")
(cd "$RELEASE_ROOT" && find . -maxdepth 1 -type f \( -name '*.deb' -o -name '*.AppImage' -o -name '*.zip' \) \
-printf '%f\n' | LC_ALL=C sort | xargs -r sha256sum > SHA256SUMS)
echo "Windows portable archive: $ARCHIVE"
echo "checksums: $RELEASE_ROOT/SHA256SUMS"

View File

@ -11,7 +11,9 @@ fi
bash -n "$BUILDER" bash -n "$BUILDER"
grep -Fq -- '-platform windows/amd64' "$BUILDER" grep -Fq -- '-platform windows/amd64' "$BUILDER"
grep -Fq -- '-compiler "$WINDOWS_CC"' "$BUILDER" grep -Fq 'CC="$WINDOWS_CC"' "$BUILDER"
grep -Fq 'CGO_ENABLED=1' "$BUILDER"
grep -Fq -- '-webview2 error' "$BUILDER"
grep -Fq 'dist-windows' "$BUILDER" grep -Fq 'dist-windows' "$BUILDER"
grep -Fq 'verstak-desktop.exe' "$BUILDER" grep -Fq 'verstak-desktop.exe' "$BUILDER"
grep -Fq 'x86_64-w64-mingw32-gcc' "$BUILDER" grep -Fq 'x86_64-w64-mingw32-gcc' "$BUILDER"

28
scripts/test-package-formats.sh Executable file
View File

@ -0,0 +1,28 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
for script in build-linux-bundle.sh package-deb.sh package-appimage.sh package-windows-portable.sh; do
path="$ROOT/scripts/$script"
if [[ ! -x "$path" ]]; then
echo "packaging script is missing or not executable: $path" >&2
exit 1
fi
bash -n "$path"
done
grep -Fq 'dpkg-deb' "$ROOT/scripts/package-deb.sh"
grep -Fq -- '--build' "$ROOT/scripts/package-deb.sh"
grep -Fq 'packaging/deb/control' "$ROOT/scripts/package-deb.sh"
grep -Fq 'libwebkit2gtk-4.1-0' "$ROOT/packaging/deb/control"
grep -Fq 'appimagetool' "$ROOT/scripts/package-appimage.sh"
grep -Fq 'WebKitWebProcess' "$ROOT/scripts/package-appimage.sh"
grep -Fq 'FixedVersionRuntime' "$ROOT/scripts/package-windows-portable.sh"
grep -Fq 'msedgewebview2.exe' "$ROOT/scripts/package-windows-portable.sh"
grep -Fq 'zip -qr' "$ROOT/scripts/package-windows-portable.sh"
grep -Fq 'WebviewBrowserPath' "$ROOT/platform_options_windows.go"
grep -Fq 'webview2' "$ROOT/platform_options_windows.go"
grep -Fq 'chmod -R a+rX' "$ROOT/scripts/build-linux-bundle.sh"
echo "desktop package script contracts passed"