From 662eaee7c347b5697a6feda63dd6763a38f6bf1c Mon Sep 17 00:00:00 2001 From: Jabster28 <29015942+Jabster28@users.noreply.github.com> Date: Tue, 8 Oct 2024 18:26:49 +0100 Subject: [PATCH] feat: add flatpak builds (#1230) --- .github/workflows/build.yml | 15 ++++- .gitignore | 2 + .../haveno/core/app/HavenoExecutable.java | 2 + desktop/package/README.md | 40 ++++++----- desktop/package/linux/Haveno.desktop | 1 + .../linux/exchange.haveno.Haveno.metainfo.xml | 66 +++++++++++++++++++ .../package/linux/exchange.haveno.Haveno.yml | 52 +++++++++++++++ desktop/package/package.gradle | 49 ++++++++++++++ docs/flatpak.md | 33 ++++++++++ 9 files changed, 240 insertions(+), 20 deletions(-) create mode 100644 desktop/package/linux/exchange.haveno.Haveno.metainfo.xml create mode 100644 desktop/package/linux/exchange.haveno.Haveno.yml create mode 100644 docs/flatpak.md diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ca9a8de1d5..832d5a619b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -40,7 +40,8 @@ jobs: if: ${{ matrix.os == 'ubuntu-22.04' }} run: | sudo apt update - sudo apt install -y rpm fuse + sudo apt install -y rpm libfuse2 flatpak flatpak-builder appstream + flatpak remote-add --if-not-exists --user flathub https://dl.flathub.org/repo/flathub.flatpakrepo - name: Install WiX Toolset if: ${{ matrix.os == 'windows-latest' }} run: | @@ -73,17 +74,19 @@ jobs: if [ "${{ matrix.os }}" == "ubuntu-22.04" ]; then mkdir ${{ github.workspace }}/release-rpm mkdir ${{ github.workspace }}/release-deb + mkdir ${{ github.workspace }}/release-flat mkdir ${{ github.workspace }}/release-appimage mv desktop/build/temp-*/binaries/haveno-*.rpm ${{ github.workspace }}/release-rpm/Haveno-${{ env.VERSION }}-linux-x86_64-installer.rpm mv desktop/build/temp-*/binaries/haveno_*.deb ${{ github.workspace }}/release-deb/Haveno-${{ env.VERSION }}-linux-x86_64-installer.deb + mv desktop/build/temp-*/binaries/*.flatpak ${{ github.workspace }}/release-flat/Haveno-${{ env.VERSION }}-linux-x86_64.flatpak mv desktop/build/temp-*/binaries/haveno_*.AppImage ${{ github.workspace }}/release-appimage/Haveno-${{ env.VERSION }}-linux-x86_64.AppImage else mv desktop/build/temp-*/binaries/Haveno-*.dmg ${{ github.workspace }}/release/Haveno-${{ env.VERSION }}-mac-installer.dmg fi - cp desktop/build/temp-*/binaries/desktop-*.jar.SHA-256 ${{ github.workspace }}/release cp desktop/build/temp-*/binaries/desktop-*.jar.SHA-256 ${{ github.workspace }}/release-deb cp desktop/build/temp-*/binaries/desktop-*.jar.SHA-256 ${{ github.workspace }}/release-rpm cp desktop/build/temp-*/binaries/desktop-*.jar.SHA-256 ${{ github.workspace }}/release-appimage + cp desktop/build/temp-*/binaries/desktop-*.jar.SHA-256 ${{ github.workspace }}/release-flat shell: bash - name: Move Release Files on Windows if: ${{ matrix.os == 'windows-latest' }} @@ -120,9 +123,17 @@ jobs: with: name: haveno-linux-rpm path: ${{ github.workspace }}/release-rpm + - uses: actions/upload-artifact@v3 name: "Linux - AppImage artifact" if: ${{ matrix.os == 'ubuntu-22.04' }} with: name: haveno-linux-appimage path: ${{ github.workspace }}/release-appimage + + - uses: actions/upload-artifact@v3 + name: "Linux - flatpak artifact" + if: ${{ matrix.os == 'ubuntu-22.04' }} + with: + name: haveno-linux-flatpak + path: ${{ github.workspace }}/release-flat diff --git a/.gitignore b/.gitignore index 75b5b82224..28973e8838 100644 --- a/.gitignore +++ b/.gitignore @@ -37,3 +37,5 @@ deploy .vscode .vim/* */.factorypath +.flatpak-builder +exchange.haveno.Haveno.yaml diff --git a/core/src/main/java/haveno/core/app/HavenoExecutable.java b/core/src/main/java/haveno/core/app/HavenoExecutable.java index aa25b12dc6..5f2d14622b 100644 --- a/core/src/main/java/haveno/core/app/HavenoExecutable.java +++ b/core/src/main/java/haveno/core/app/HavenoExecutable.java @@ -82,6 +82,8 @@ import java.util.concurrent.atomic.AtomicInteger; @Slf4j public abstract class HavenoExecutable implements GracefulShutDownHandler, HavenoSetup.HavenoSetupListener, UncaughtExceptionHandler { + // TODO: regular expression is used to parse application name for the flatpak manifest, a more stable approach would be nice + // Don't edit the next line unless you're only editing in between the quotes. public static final String DEFAULT_APP_NAME = "Haveno"; public static final int EXIT_SUCCESS = 0; diff --git a/desktop/package/README.md b/desktop/package/README.md index 61bf0260dc..1b36b5ce22 100644 --- a/desktop/package/README.md +++ b/desktop/package/README.md @@ -3,20 +3,23 @@ Follow these instructions to create installers for the Haveno Java desktop appli > **Note** > These steps will delete the previously built Haveno binaries, so they'll need rebuilt after. -### Linux +## Linux From x86_64 machine: 1. `sudo apt-get update` -2. `sudo apt install -y rpm fuse` +2. `sudo apt install -y rpm fuse flatpak flatpak-builder` 1. `./gradlew clean build --refresh-keys --refresh-dependencies` (or `make clean && skip-tests` after refreshed) 2. `./gradlew packageInstallers` 3. Confirm prompts. 4. Path to installer is printed at the end. Execute to install, e.g.: `sudo dpkg -i .deb` or open `.deb` with Software Install. +Note: Please see [flatpak.md](../../docs/flatpak.md) for information on +distributing Haveno via Flatpak. + Haveno data folder on Linux: `/home//.local/share/Haveno/` -### macOS +## macOS From x86_64 machine: @@ -31,7 +34,7 @@ From x86_64 machine: Haveno data folder on Mac: `/Users//Library/Application Support/Haveno/` -### Windows +## Windows 1. Enable .NET Framework 3.5: 1. Open the Control Panel on your Windows system. @@ -42,7 +45,7 @@ Haveno data folder on Mac: `/Users//Library/Application Support/Haveno 6. Click "OK" to save the changes and exit the dialog box. 7. Windows will download and install the required files and components to enable the .NET Framework 3.5. This may take several minutes, depending on your internet connection speed and system configuration. 8. Once the installation is complete, you will need to restart your computer to apply the changes. -2. Install Wix Toolset 3: https://github.com/wixtoolset/wix3/releases/tag/wix314rtm +2. Install Wix Toolset 3: 3. Open MSYS2 for the following commands. 4. `export PATH=$PATH:$JAVA_HOME/bin:"C:\Program Files (x86)\WiX Toolset v3.14\bin"` 5. `./gradlew clean build --refresh-keys --refresh-dependencies` (or `make clean && skip-tests` after refreshed) @@ -52,32 +55,32 @@ Haveno data folder on Mac: `/Users//Library/Application Support/Haveno Haveno data folder on Windows: `~\AppData\Roaming\Haveno\` -## Copy installer and rebuild Haveno binaries +## Copying installer and rebuilding Haveno binaries 1. Copy the installer to a safe location because it will be deleted in the next step. 2. `make clean && make` (or `make clean && make skip-tests`) to rebuild Haveno apps. - ## Additional Notes ### Icons -Icons (Haveno.zip) were obtained from https://github.com/haveno-dex/haveno-meta/issues/1#issuecomment-819741689. +Icons (Haveno.zip) were obtained from . -#### Linux +### Building for Linux The linux package requires the correct packaging tools installed. You may run into the following errors: -``` +```sh Error: Invalid or unsupported type: [deb] ``` -``` + +```sh Error: Invalid or unsupported type: [rpm] ``` On Ubuntu, resolve by running `sudo apt install rpm`. For deb, ensure dpkg is installed. -``` +```sh Exception in thread "main" java.io.IOException: Failed to rename /tmp/Haveno-stripped15820156885694375398.tmp to /storage/src/haveno/desktop/build/libs/fatJar/desktop-1.0.0-SNAPSHOT-all.jar at haveno.tools.Utils.renameFile(Utils.java:36) at io.github.zlika.reproducible.StipZipFile.strip(StipZipFile.java:35) @@ -87,20 +90,21 @@ Exception in thread "main" java.io.IOException: Failed to rename /tmp/Haveno-str This may happen if the source folder is on a different hard drive than the system `tmp` folder. The tools-1.0.jar calls renameTo to rename the deterministic jar back to the fat jar location. You can temporarily change your temp directory on linux: -``` +```sh export _JAVA_OPTIONS="-Djava.io.tmpdir=/storage/tmp" ``` -#### MacOs +### Building for macOS -Svg was converted into a 1024x1024 pixel PNG using https://webkul.github.io/myscale/, then converted to icns for macosx -here https://cloudconvert.com/png-to-icns +Svg was converted into a 1024x1024 pixel PNG using +, then converted to icns for macosx +here -##### Known Issues +#### Known Issues Signing is not implemented. -#### Windows +### Building for Windows Pngs were resized and pasted into the WixUi images using paint. [CloudConvert](https://cloudconvert.com) was used to convert the Haveno png icon to ico. diff --git a/desktop/package/linux/Haveno.desktop b/desktop/package/linux/Haveno.desktop index 82add1740d..a0e32a6347 100644 --- a/desktop/package/linux/Haveno.desktop +++ b/desktop/package/linux/Haveno.desktop @@ -11,3 +11,4 @@ Terminal=false Type=Application MimeType= X-AppImage-Name=Haveno +StartupWMClass=Haveno diff --git a/desktop/package/linux/exchange.haveno.Haveno.metainfo.xml b/desktop/package/linux/exchange.haveno.Haveno.metainfo.xml new file mode 100644 index 0000000000..f07c72d204 --- /dev/null +++ b/desktop/package/linux/exchange.haveno.Haveno.metainfo.xml @@ -0,0 +1,66 @@ + + + exchange.haveno.Haveno + + exchange.haveno.Haveno.desktop + Haveno + Decentralized P2P exchange built on Monero and Tor + + Office + Finance + P2P + + + cryptocurrency + monero + + + + CC-BY-4.0 + AGPL-3.0-only + + #e5a29f + #562c63 + + + pointing + keyboard + touch + + + +

Haveno (pronounced ha‧ve‧no) is a platform for people who want to exchange Monero for fiat currencies like EUR, GBP, and USD or other cryptocurrencies like BTC, ETH, and BCH.

+
    +
  • All communications are routed through Tor, to preserve your privacy +
  • +
  • Trades are peer-to-peer: trades on Haveno will happen between people only, there is no central authority. +
  • +
  • Trades are non-custodial: Haveno provides arbitration in case something goes wrong during the trade, but we will never have access to your funds. +
  • +
  • There is No token, because we don't need it. Transactions between traders are secured by non-custodial multisignature transactions on the Monero network. +
  • +
+ +
+ + + https://files.catbox.moe/8pahgg.png + Recent Trades page + + + + + woodser + + https://haveno.exchange + https://github.com/haveno-dex/haveno/issues + + moderate + moderate + intense + intense + + + + Haveno.desktop +
diff --git a/desktop/package/linux/exchange.haveno.Haveno.yml b/desktop/package/linux/exchange.haveno.Haveno.yml new file mode 100644 index 0000000000..2924684435 --- /dev/null +++ b/desktop/package/linux/exchange.haveno.Haveno.yml @@ -0,0 +1,52 @@ +id: exchange.haveno.Haveno +runtime: org.freedesktop.Platform +runtime-version: "23.08" +sdk: org.freedesktop.Sdk +sdk-extensions: + - org.freedesktop.Sdk.Extension.openjdk21 +command: /app/bin/Haveno +modules: + - name: openjdk + buildsystem: simple + build-commands: + - /usr/lib/sdk/openjdk21/install.sh + - name: Haveno + buildsystem: simple + sources: + # - type: git + # url: https://github.com/haveno-dex/haveno + - type: dir + path: build + - type: file + path: package/linux/Haveno.desktop + - type: file + path: package/linux/exchange.haveno.Haveno.metainfo.xml + - type: file + path: package/linux/icon.png + build-commands: + - ls + - pwd + # TODO: consider switching from reading from a deb to reading from jpackage's image + - mv temp-*/binaries/haveno_*.deb haveno.deb + - ar x haveno.deb + - tar xf data.tar.* + - cp -r opt/haveno/lib /app/lib + - install -D opt/haveno/bin/Haveno /app/bin/Haveno + - mkdir -p /app/share/icons/hicolor/128x128/apps/ + - mkdir -p /app/share/applications/ + - mkdir -p /app/share/metainfo/ + - mv icon.png /app/share/icons/hicolor/128x128/apps/haveno.png + - mv Haveno.desktop /app/share/applications/exchange.haveno.Haveno.desktop + - mv exchange.haveno.Haveno.metainfo.xml /app/share/metainfo/ + +# TODO: xdg-open fails +finish-args: + - --env=PATH=/app/jre/bin:/usr/bin:$PATH + # - --env=JAVA_HOME=/app/jre + - --env=JAVA_HOME=/usr/lib/sdk/openjdk21/ + - --device=dri + - --talk-name=org.freedesktop.Notifications + - --talk-name=org.freedesktop.secrets + - --share=network + - --share=ipc + - --socket=x11 diff --git a/desktop/package/package.gradle b/desktop/package/package.gradle index df41edb895..78f15cba8d 100644 --- a/desktop/package/package.gradle +++ b/desktop/package/package.gradle @@ -1,6 +1,7 @@ import org.apache.tools.ant.taskdefs.condition.Os import java.time.LocalDateTime +import java.util.regex.Pattern task jpackageSanityChecks { description 'Interactive sanity checks on the version of the code that will be packaged' @@ -394,6 +395,54 @@ task packageInstallers { executeCmd(jPackageFilePath + commonOpts + linuxOpts + " --linux-rpm-license-type AGPLv3" + // https://fedoraproject.org/wiki/Licensing:Main?rd=Licensing#Good_Licenses " --type rpm") + + + + // Define Flatpak-related properties + String flatpakManifestFile = 'package/linux/exchange.haveno.Haveno.yml' + String linuxDir = 'package/linux' + String flatpakOutputDir = 'package/linux/build' + String flatpakExportDir = "${binariesFolderPath}/fpexport" + String flatpakBundleFile = "${binariesFolderPath}/haveno.flatpak" + + // Read the default app name from the HavenoExecutable.java file + def filer = file('../core/src/main/java/haveno/core/app/HavenoExecutable.java') + def content = filer.text + def matcher = Pattern.compile(/public static final String DEFAULT_APP_NAME = "(.*?)";/).matcher(content) + def defaultAppName = "Haveno" + if (matcher.find()) { + defaultAppName = matcher.group(1) + } else { + throw new GradleException("DEFAULT_APP_NAME not found in HavenoExecutable.java") + } + // copy the manifest to a new tmp one in the same place + // and add a --filesystem=.local/share/${name} to the flatpak manifest + def manifest = file(flatpakManifestFile) + def newManifest = file('exchange.haveno.Haveno.yaml') + newManifest.write(manifest.text.replace("- --share=network", "- --share=network\n - --filesystem=~/.local/share/${defaultAppName}:create")) + flatpakManifestFile = 'exchange.haveno.Haveno.yaml' + + // Command to build the Flatpak + exec { + commandLine 'flatpak-builder', '--force-clean', flatpakOutputDir, flatpakManifestFile, '--user', '--install-deps-from=flathub' + } + + // Command to export the Flatpak + exec { + commandLine 'flatpak', 'build-export', flatpakExportDir, flatpakOutputDir + } + + // Command to create the Flatpak bundle + exec { + commandLine 'flatpak', 'build-bundle', flatpakExportDir, flatpakBundleFile, 'exchange.haveno.Haveno', '--runtime-repo=https://flathub.org/repo/flathub.flatpakrepo' + } + + // delete the flatpak build directory + delete(flatpakOutputDir) + delete(flatpakExportDir) + delete(flatpakManifestFile) + + println "Flatpak package created at ${flatpakBundleFile}" } // Env variable can be set by calling "export HAVENO_SHARED_FOLDER='Some value'" diff --git a/docs/flatpak.md b/docs/flatpak.md new file mode 100644 index 0000000000..d2ecdcdf84 --- /dev/null +++ b/docs/flatpak.md @@ -0,0 +1,33 @@ +# Flatpak distribution + +The `.flatpak` binary files (known as "bundles") that +`./gradlew packageInstallers` creates can be used to download and install +Haveno, but there are several security issues that arise in Flatpak when only +using the bundle files: + +- There is no +[digital signature](https://en.wikipedia.org/wiki/Digital_signature), +if a bad actor were to upload a malicious `.flatpak` the users would have no +way to tell when upgrading. +- Upgrading isn't as easy, your users need to find the new Flatpak bundle file, +and you cannot update multiple apps easily. + - This also makes an accidental downgrade much more likely. + +Flatpak has a solution for these issues, a +[Flatpak repository](https://docs.flatpak.org/en/latest/repositories.html). +Flatpak repos store the data of their apps within an OSTree (almost like git) +repository, and the commits can be signed with a GPG key. The nature of OSTree +also allows for easy updates, as the Flatpak client can download deltas of the +changes instead of the entire file. + +If you plan on distributing Haveno as a Flatpak, it's recommended to create a +Flatpak repository as well. This guide will show you how to create a Flatpak +repository for Haveno. The official documentation states that [it's possible to +use GitHub/Lab Pages](https://docs.flatpak.org/en/latest/hosting-a-repository.html#hosting-a-repository-on-gitlab-github-pages) +to host the repository, but this hasn't been tested. The more common way is to +use a web server, or something like +[flat-manager](https://github.com/flatpak/flat-manager). + +An example Haveno flat-manager solution using `docker-compose` has been created +and documented at if you +want a quick way to get started. Note that this does require an always-on server.