From ab5c541e692410cc2711f8e0434fa2b77bfedd5b Mon Sep 17 00:00:00 2001 From: Gregory Schier Date: Tue, 10 Feb 2026 16:20:25 -0800 Subject: [PATCH] Flatpak: build from source instead of repackaging debs - Rewrite Flatpak manifest to build from source using SDK extensions (node22, rust-stable) with offline cargo/npm dependency caches - Add generate-sources.sh to produce cargo-sources.json and node-sources.json from lock files using flatpak-builder-tools - Vendor Node.js, protoc, and wasm-pack as archive sources with SHA256 verification and per-arch support - Add SHA256 verification to vendor-node.cjs and vendor-protoc.cjs - Rewrite update-manifest.sh to update git tag/commit and regenerate dependency sources - Update Flathub CI workflow to install generators and copy source files - Remove stale plugins/faker entry from package-lock.json --- .github/workflows/flathub.yml | 14 ++++ .gitignore | 3 + flatpak/app.yaak.Yaak.yml | 136 ++++++++++++++++++++++++++++++---- flatpak/generate-sources.sh | 81 ++++++++++++++++++++ flatpak/update-manifest.sh | 54 ++++++-------- package-lock.json | 12 --- scripts/vendor-node.cjs | 20 +++++ scripts/vendor-protoc.cjs | 20 +++++ 8 files changed, 284 insertions(+), 56 deletions(-) create mode 100755 flatpak/generate-sources.sh diff --git a/.github/workflows/flathub.yml b/.github/workflows/flathub.yml index 98d95e02..6e14ec74 100644 --- a/.github/workflows/flathub.yml +++ b/.github/workflows/flathub.yml @@ -16,6 +16,16 @@ jobs: - name: Checkout app repo uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: Install source generators + run: | + pip install flatpak-node-generator tomlkit aiohttp + git clone --depth 1 https://github.com/flatpak/flatpak-builder-tools flatpak/flatpak-builder-tools + - name: Run update-manifest.sh run: bash flatpak/update-manifest.sh "${{ github.event.release.tag_name }}" @@ -29,8 +39,12 @@ jobs: - name: Copy updated files to Flathub repo run: | cp flatpak/app.yaak.Yaak.yml flathub-repo/ + cp flatpak/app.yaak.Yaak.metainfo.xml flathub-repo/ + cp flatpak/cargo-sources.json flathub-repo/ + cp flatpak/node-sources.json flathub-repo/ cp LICENSE flathub-repo/ sed -i 's|path: \.\./LICENSE|path: LICENSE|' flathub-repo/app.yaak.Yaak.yml + sed -i 's|flatpak/app.yaak.Yaak.metainfo.xml|app.yaak.Yaak.metainfo.xml|' flathub-repo/app.yaak.Yaak.yml - name: Commit and push to Flathub working-directory: flathub-repo diff --git a/.gitignore b/.gitignore index a8773a8a..40c48bd8 100644 --- a/.gitignore +++ b/.gitignore @@ -48,3 +48,6 @@ crates-tauri/yaak-app/tauri.worktree.conf.json # Flatpak build artifacts flatpak-repo/ .flatpak-builder/ +flatpak/flatpak-builder-tools/ +flatpak/cargo-sources.json +flatpak/node-sources.json diff --git a/flatpak/app.yaak.Yaak.yml b/flatpak/app.yaak.Yaak.yml index ad4e5817..855521a9 100644 --- a/flatpak/app.yaak.Yaak.yml +++ b/flatpak/app.yaak.Yaak.yml @@ -2,7 +2,12 @@ id: app.yaak.Yaak runtime: org.gnome.Platform runtime-version: "49" sdk: org.gnome.Sdk -command: yaak-app +command: yaak + +sdk-extensions: + - org.freedesktop.Sdk.Extension.node22 + - org.freedesktop.Sdk.Extension.rust-stable + rename-desktop-file: yaak.desktop rename-icon: yaak-app @@ -36,26 +41,129 @@ modules: - name: yaak buildsystem: simple + build-options: + append-path: /app/bin:/usr/lib/sdk/node22/bin:/usr/lib/sdk/rust-stable/bin + env: + CARGO_HOME: /run/build/yaak/cargo + XDG_CACHE_HOME: /run/build/yaak/flatpak-node/cache + npm_config_cache: /run/build/yaak/flatpak-node/npm-cache + npm_config_offline: "true" + npm_config_nodedir: /usr/lib/sdk/node22 + NODE_OPTIONS: --max_old_space_size=4096 + build-commands: - - ar -x yaak.deb - - tar -xf data.tar.gz - - mv usr/bin/* /app/bin - - mv usr/lib/* /app/lib - - mv usr/share/* /app/share + # Vendor Node.js binary (sidecar for plugin runtime) + - mkdir -p crates-tauri/yaak-app/vendored/node + - install -Dm755 vendored-node/bin/node crates-tauri/yaak-app/vendored/node/yaaknode + + # Vendor protoc binary and includes + - mkdir -p crates-tauri/yaak-app/vendored/protoc + - install -Dm755 protoc-bin/bin/protoc crates-tauri/yaak-app/vendored/protoc/yaakprotoc + - cp -r protoc-bin/include crates-tauri/yaak-app/vendored/protoc/include + + # Install wasm-pack (needed for yaak-templates WASM build) + - install -Dm755 vendored-wasm-pack/wasm-pack /app/bin/wasm-pack + + # Install npm dependencies offline + - npm ci --offline + + # Pre-fetch Cargo dependencies offline + - cargo --offline fetch --manifest-path Cargo.toml + + # Build all workspace packages (frontend, plugins, wasm, plugin-runtime) + - npm run build + + # Copy built plugins to vendored directory + - npm run vendor:vendor-plugins + + # Build the Tauri app (Rust backend + bundle as deb for icon/desktop extraction) + # Override beforeBuildCommand since we already built the frontend and dependencies above + - >- + npx tauri build -b deb + --config crates-tauri/yaak-app/tauri.linux.conf.json + --config '{"build":{"beforeBuildCommand":""}}' + + # Install binary + - install -Dm755 crates-tauri/yaak-app/target/release/yaak /app/bin/yaak-app + + # Install icons from the deb bundle + - cp -r crates-tauri/yaak-app/target/release/bundle/deb/*/data/usr/share/icons /app/share/icons + + # Install desktop file + - install -Dm644 crates-tauri/yaak-app/target/release/bundle/deb/*/data/usr/share/applications/yaak.desktop /app/share/applications/yaak.desktop + + # Install metainfo and license + - install -Dm644 flatpak/app.yaak.Yaak.metainfo.xml /app/share/metainfo/app.yaak.Yaak.metainfo.xml - install -Dm644 LICENSE /app/share/licenses/app.yaak.Yaak/LICENSE sources: - - type: file - dest-filename: yaak.deb - url: https://github.com/mountain-loop/yaak/releases/download/v2026.1.2/yaak_2026.1.2_amd64.deb - sha256: "c4236b5bcf391e579dc79b71c3b5c58f6f9bfc6c175fc70426d0ca85799beba5" + # Application source + - type: git + url: https://github.com/mountain-loop/yaak.git + tag: v2026.1.2 + commit: bd7e840a5700ddefb5ef1f22771cc5555000f777 + x-checker-data: + type: git + tag-pattern: ^v(\d+\.\d+\.\d+)$ + + # Offline npm dependencies + - node-sources.json + + # Offline Cargo dependencies + - cargo-sources.json + + # Vendored Node.js binary (x86_64) + - type: archive + url: https://nodejs.org/download/release/v24.11.1/node-v24.11.1-linux-x64.tar.gz + sha256: 58a5ff5cc8f2200e458bea22e329d5c1994aa1b111d499ca46ec2411d58239ca + strip-components: 1 + dest: vendored-node only-arches: - x86_64 - - type: file - dest-filename: yaak.deb - url: https://github.com/mountain-loop/yaak/releases/download/v2026.1.2/yaak_2026.1.2_arm64.deb - sha256: "9ba9b7c9df56ffb9b801e40cb38685f1650cf7e2f9e85dad0ae3329f8e01ff6d" + + # Vendored Node.js binary (aarch64) + - type: archive + url: https://nodejs.org/download/release/v24.11.1/node-v24.11.1-linux-arm64.tar.gz + sha256: 0dc93ec5c798b0d347f068db6d205d03dea9a71765e6a53922b682b91265d71f + strip-components: 1 + dest: vendored-node only-arches: - aarch64 + + # wasm-pack binary (x86_64) + - type: archive + url: https://github.com/drager/wasm-pack/releases/download/v0.13.1/wasm-pack-v0.13.1-x86_64-unknown-linux-musl.tar.gz + sha256: c539d91ccab2591a7e975bcf82c82e1911b03335c80aa83d67ad25ed2ad06539 + strip-components: 1 + dest: vendored-wasm-pack + only-arches: + - x86_64 + + # wasm-pack binary (aarch64) + - type: archive + url: https://github.com/drager/wasm-pack/releases/download/v0.13.1/wasm-pack-v0.13.1-aarch64-unknown-linux-musl.tar.gz + sha256: 2e65038769f8bbaa5fc237ad4bb523e692df99458cbd3e3d92525b89d8762379 + strip-components: 1 + dest: vendored-wasm-pack + only-arches: + - aarch64 + + # Vendored protoc binary and includes (x86_64) + - type: archive + url: https://github.com/protocolbuffers/protobuf/releases/download/v33.1/protoc-33.1-linux-x86_64.zip + sha256: f3340e28a83d1c637d8bafdeed92b9f7db6a384c26bca880a6e5217b40a4328b + dest: protoc-bin + only-arches: + - x86_64 + + # Vendored protoc binary and includes (aarch64) + - type: archive + url: https://github.com/protocolbuffers/protobuf/releases/download/v33.1/protoc-33.1-linux-aarch_64.zip + sha256: 6018147740548e0e0f764408c87f4cd040e6e1c1203e13aeacaf811892b604f3 + dest: protoc-bin + only-arches: + - aarch64 + + # License file - type: file path: ../LICENSE diff --git a/flatpak/generate-sources.sh b/flatpak/generate-sources.sh new file mode 100755 index 00000000..a198c203 --- /dev/null +++ b/flatpak/generate-sources.sh @@ -0,0 +1,81 @@ +#!/usr/bin/env bash +# +# Generate offline dependency source files for Flatpak builds. +# +# Prerequisites: +# pip install flatpak-node-generator tomlkit aiohttp +# Clone https://github.com/flatpak/flatpak-builder-tools (for cargo generator) +# +# Usage: +# ./flatpak/generate-sources.sh +# +# This script generates: +# flatpak/cargo-sources.json - Cargo crate sources from Cargo.lock +# flatpak/node-sources.json - npm package sources from package-lock.json + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" + +# Check for flatpak-cargo-generator.py +CARGO_GENERATOR="" +if command -v flatpak-cargo-generator.py &>/dev/null; then + CARGO_GENERATOR="flatpak-cargo-generator.py" +elif [ -f "$SCRIPT_DIR/flatpak-builder-tools/cargo/flatpak-cargo-generator.py" ]; then + CARGO_GENERATOR="python3 $SCRIPT_DIR/flatpak-builder-tools/cargo/flatpak-cargo-generator.py" +else + echo "Error: flatpak-cargo-generator.py not found." + echo "Either install it in PATH or clone flatpak-builder-tools:" + echo " cd $SCRIPT_DIR && git clone https://github.com/flatpak/flatpak-builder-tools" + exit 1 +fi + +# Check for flatpak-node-generator +if ! command -v flatpak-node-generator &>/dev/null; then + echo "Error: flatpak-node-generator not found." + echo "Install it with: pip install flatpak-node-generator" + exit 1 +fi + +echo "Generating cargo-sources.json..." +$CARGO_GENERATOR -o "$SCRIPT_DIR/cargo-sources.json" "$REPO_ROOT/Cargo.lock" +echo " Done: flatpak/cargo-sources.json" + +echo "Generating node-sources.json..." + +# flatpak-node-generator doesn't handle npm workspace packages (local paths +# without "resolved" or "link" fields). Strip them from a temp copy of the +# lockfile before running the generator. +TMPDIR=$(mktemp -d) +trap 'rm -rf "$TMPDIR"' EXIT + +python3 -c " +import json, sys, shutil +with open(sys.argv[1]) as f: + data = json.load(f) +packages = data.get('packages', {}) +to_remove = [] +for name, info in packages.items(): + if not name: + continue + if info.get('link'): + continue + if 'resolved' in info: + continue + # No 'resolved' and not a link — this is a local workspace package + to_remove.append(name) +for name in to_remove: + del packages[name] +with open(sys.argv[2], 'w') as f: + json.dump(data, f, indent=2) +# Copy package.json so the generator can read the root entry +shutil.copy2(sys.argv[3], sys.argv[4]) +print(f'Stripped {len(to_remove)} local workspace packages from lockfile', file=sys.stderr) +" "$REPO_ROOT/package-lock.json" "$TMPDIR/package-lock.json" "$REPO_ROOT/package.json" "$TMPDIR/package.json" + +flatpak-node-generator --no-requests-cache -o "$SCRIPT_DIR/node-sources.json" npm "$TMPDIR/package-lock.json" +echo " Done: flatpak/node-sources.json" + +echo "" +echo "Source files generated. Commit them alongside the manifest." diff --git a/flatpak/update-manifest.sh b/flatpak/update-manifest.sh index e75c6186..86ae1f86 100755 --- a/flatpak/update-manifest.sh +++ b/flatpak/update-manifest.sh @@ -1,15 +1,15 @@ #!/usr/bin/env bash # -# Update the Flatpak manifest with URLs and SHA256 hashes for a given release. +# Update the Flatpak manifest for a new release. # # Usage: # ./flatpak/update-manifest.sh v2026.2.0 # # This script: -# 1. Downloads the x86_64 and aarch64 .deb files from the GitHub release -# 2. Computes their SHA256 checksums -# 3. Updates the manifest YAML with the correct URLs and hashes -# 4. Updates the metainfo.xml with a new entry +# 1. Resolves the git commit for the given tag +# 2. Updates the manifest YAML with the new tag and commit +# 3. Updates the metainfo.xml with a new entry +# 4. Regenerates cargo-sources.json and node-sources.json set -euo pipefail @@ -33,37 +33,24 @@ if [[ "$VERSION" == *-* ]]; then fi REPO="mountain-loop/yaak" -BASE_URL="https://github.com/$REPO/releases/download/$VERSION_TAG" -DEB_AMD64="yaak_${VERSION}_amd64.deb" -DEB_ARM64="yaak_${VERSION}_arm64.deb" - -TMPDIR=$(mktemp -d) -trap 'rm -rf "$TMPDIR"' EXIT - -echo "Downloading $DEB_AMD64..." -curl -fSL "$BASE_URL/$DEB_AMD64" -o "$TMPDIR/$DEB_AMD64" -SHA_AMD64=$(sha256sum "$TMPDIR/$DEB_AMD64" | cut -d' ' -f1) -echo " SHA256: $SHA_AMD64" - -echo "Downloading $DEB_ARM64..." -curl -fSL "$BASE_URL/$DEB_ARM64" -o "$TMPDIR/$DEB_ARM64" -SHA_ARM64=$(sha256sum "$TMPDIR/$DEB_ARM64" | cut -d' ' -f1) -echo " SHA256: $SHA_ARM64" +# Resolve the commit hash for this tag +echo "Resolving commit for tag $VERSION_TAG..." +COMMIT=$(git ls-remote "https://github.com/$REPO.git" "refs/tags/$VERSION_TAG" | cut -f1) +if [ -z "$COMMIT" ]; then + echo "Error: Could not resolve commit for tag '$VERSION_TAG'" + exit 1 +fi +echo " Commit: $COMMIT" echo "" echo "Updating manifest: $MANIFEST" -# Update URLs by matching the arch-specific deb filename -sed -i "s|url: .*amd64\.deb|url: $BASE_URL/$DEB_AMD64|" "$MANIFEST" -sed -i "s|url: .*arm64\.deb|url: $BASE_URL/$DEB_ARM64|" "$MANIFEST" +# Update tag +sed -i "s|tag: v[0-9.]*$|tag: $VERSION_TAG|" "$MANIFEST" -# Update SHA256 hashes by finding the current ones and replacing -OLD_SHA_AMD64=$(grep -A2 "amd64\.deb" "$MANIFEST" | grep sha256 | sed 's/.*"\(.*\)"/\1/') -OLD_SHA_ARM64=$(grep -A2 "arm64\.deb" "$MANIFEST" | grep sha256 | sed 's/.*"\(.*\)"/\1/') - -sed -i "s|$OLD_SHA_AMD64|$SHA_AMD64|" "$MANIFEST" -sed -i "s|$OLD_SHA_ARM64|$SHA_ARM64|" "$MANIFEST" +# Update commit +sed -i "s|commit: [0-9a-f]\{40\}|commit: $COMMIT|" "$MANIFEST" echo " Manifest updated." @@ -76,7 +63,14 @@ sed -i "s| | \n