build: add portable desktop packages
This commit is contained in:
parent
f4e911c14a
commit
20952e8477
|
|
@ -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/
|
||||||
|
|
|
||||||
72
README.md
72
README.md
|
|
@ -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
|
||||||
|
|
|
||||||
6
main.go
6
main.go
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
#!/usr/bin/env sh
|
||||||
|
exec /opt/verstak/verstak-desktop "$@"
|
||||||
|
|
@ -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" "$@"
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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 |
|
|
@ -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" %*
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
//go:build !windows
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "github.com/wailsapp/wails/v2/pkg/options"
|
||||||
|
|
||||||
|
func applyPlatformOptions(_ *options.App) {}
|
||||||
|
|
@ -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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "path/filepath"
|
||||||
|
|
||||||
|
func bundledWebView2Path(executablePath string) string {
|
||||||
|
return filepath.Join(filepath.Dir(executablePath), "webview2")
|
||||||
|
}
|
||||||
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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"
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
@ -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"
|
||||||
|
|
@ -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"
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
Loading…
Reference in New Issue