diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 75830f541..fd79238af 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -12,6 +12,8 @@ on: env: # we need to install specific version because of this bug: https://github.com/dotnet/sdk/issues/24037 FSXC_VERSION: 0.5.9.1 + GtkSharpVersion: 3.24.24.117-develop + DotNetVersionForMauiGtk: 8.0.200 # FIXME: figure out why we need to clean after make if we # want 'make strict' target to really happen without @@ -19,16 +21,19 @@ env: # (msbuild bug?) jobs: - macOS--dotnet6-and-mono: + macOS--dotnet8-and-mono: runs-on: macOS-13 + env: + # make it work with newer .NET + DOTNET_ROLL_FORWARD: 'Major' steps: - uses: actions/checkout@v1 with: submodules: false - - name: Setup .NET SDK 6.0.x + - name: Setup .NET SDK 8.0.x uses: actions/setup-dotnet@v1.7.2 with: - dotnet-version: '6.0.113' + dotnet-version: '8.0.300' - name: Install specific Xamarin.iOS and Xamarin.Android versions run: | wget https://download.visualstudio.microsoft.com/download/pr/81c41aaa-a3d7-4875-8416-d04b472379b7/21d9f6c5ad3a6bc2479b2ec4b0685b6c/xamarin.ios-16.0.0.72.pkg @@ -39,11 +44,30 @@ jobs: run: | mono --version /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/bin/mtouch --version - ls -l /Library/Frameworks/Xamarin.Android.framework/Versions/ + ls -l /Library/Frameworks/Xamarin.Android.framework/Versions/ + - name: install maui workload + run: dotnet workload install maui - name: configure run: ./configure.sh - name: build in DEBUG mode run: make + - name: Build Android APK + run: dotnet publish src/GWallet.Frontend.Maui/GWallet.Frontend.Maui.fsproj --framework net8.0-android --configuration Release + # Upload artifact fails with "permission denied" error without this + - name: Fix permissions + run: sudo chmod -R 755 src/GWallet.Frontend.Maui/bin/Release/net8.0-android/publish + - name: Find the APK file's path and name + id: find_apk_file + run: | + FILEPATH=$(ls src/GWallet.Frontend.Maui/bin/Release/net8.0-android/publish/*.apk) + FILENAME=$(basename $FILEPATH) + echo "file_path=$FILEPATH" >> $GITHUB_OUTPUT + echo "file_name=$FILENAME" >> $GITHUB_OUTPUT + - name: Upload APK as CI artifact + uses: actions/upload-artifact@v3 + with: + path: ${{ steps.find_apk_file.outputs.file_path }} + name: ${{ steps.find_apk_file.outputs.file_name }} - name: sanity check run: make sanitycheck - name: unit tests @@ -96,16 +120,16 @@ jobs: - name: integration tests run: make update-servers - macOS--dotnet6-only: + macOS--dotnet8-only: runs-on: macOS-13 steps: - uses: actions/checkout@v1 with: submodules: false - - name: Setup .NET SDK 6.0.x + - name: Setup .NET SDK 8.0.x uses: actions/setup-dotnet@v1.7.2 with: - dotnet-version: '6.0.113' + dotnet-version: '8.0.300' - name: HACK to emulate mono uninstall run: sudo rm -f `which mono` && sudo rm -f `which msbuild` - name: configure @@ -127,19 +151,23 @@ jobs: dotnet new tool-manifest dotnet tool install fsxc --version ${{ env.FSXC_VERSION }} + # make it work with newer .NET + export DOTNET_ROLL_FORWARD=Major find . -type f -name "*.fsx" | xargs -t -I {} dotnet fsxc {} - windows--dotnet6-and-legacyFramework: + windows--dotnet8-and-legacyFramework: runs-on: windows-latest steps: - uses: actions/checkout@v1 with: submodules: false - - name: Setup .NET SDK 6.0.x + - name: Setup .NET SDK 8.0.x uses: actions/setup-dotnet@v1.7.2 with: - dotnet-version: '6.0.113' + dotnet-version: '8.0.x' + - name: install maui workloads + run: dotnet workload install maui - name: configure run: .\configure.bat - name: build in DEBUG mode @@ -160,6 +188,8 @@ jobs: dotnet new tool-manifest dotnet tool install fsxc --version ${{ env.FSXC_VERSION }} + # make it work with newer .NET + export DOTNET_ROLL_FORWARD=Major find . -type f -name "*.fsx" | xargs -t -I {} dotnet fsxc {} @@ -186,18 +216,20 @@ jobs: - name: integration tests run: .\make update-servers - windows--dotnet6-only: + windows--dotnet8-only: runs-on: windows-latest steps: - uses: actions/checkout@v1 with: submodules: false - - name: Setup .NET SDK 6.0.x + - name: Setup .NET SDK 8.0.x uses: actions/setup-dotnet@v1.7.2 with: - dotnet-version: '6.0.113' + dotnet-version: '8.0.x' - name: HACK to emulate legacy .NETFramework uninstall run: del $(& "${Env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" -find MSBuild\\**\\Bin\\MSBuild.exe) + - name: install maui workloads + run: dotnet workload install maui - name: configure run: .\configure.bat - name: build in DEBUG mode @@ -218,6 +250,8 @@ jobs: dotnet new tool-manifest dotnet tool install fsxc --version ${{ env.FSXC_VERSION }} + # make it work with newer .NET + export DOTNET_ROLL_FORWARD=Major find . -type f -name "*.fsx" | xargs -t -I {} dotnet fsxc {} @@ -226,7 +260,13 @@ jobs: steps: - uses: actions/checkout@v1 with: - submodules: false + submodules: true + - name: Setup .NET SDK ${{ env.DotNetVersionForMauiGtk }} + uses: actions/setup-dotnet@v1.7.2 + with: + dotnet-version: ${{ env.DotNetVersionForMauiGtk }} + - name: Install gtk workload & add Maui Nuget source + run: ./scripts/prepare_maui_gtk.sh - name: install missing dependencies run: sudo apt install --yes fsharp nunit-console - name: check mono version @@ -250,8 +290,11 @@ jobs: dotnet new tool-manifest dotnet tool install fsxc --version ${{ env.FSXC_VERSION }} + # make it work with newer .NET + export DOTNET_ROLL_FORWARD=Major - find . -type f -name "*.fsx" | xargs -t -I {} dotnet fsxc {} + # ignore scripts/fsx submodule as compiling scripts there will result in error + find . -type f -name "*.fsx" ! -path "./scripts/fsx/*" | xargs -t -I {} dotnet fsxc {} linux-github--dotnet-and-newmono: runs-on: ubuntu-22.04 @@ -287,6 +330,8 @@ jobs: dotnet new tool-manifest dotnet tool install fsxc --version ${{ env.FSXC_VERSION }} + # make it work with newer .NET + export DOTNET_ROLL_FORWARD=Major find . -type f -name "*.fsx" | xargs -t -I {} dotnet fsxc {} @@ -330,7 +375,7 @@ jobs: - name: integration tests run: make update-servers - linux-vanilla--stockdotnet6-only: + linux-vanilla--stockdotnet8-only: runs-on: ubuntu-22.04 container: image: "ubuntu:22.04" @@ -343,7 +388,7 @@ jobs: - name: install sudo run: apt update && apt install --yes sudo - name: install all dependencies - run: sudo DEBIAN_FRONTEND=noninteractive apt install --yes git make dotnet6 + run: sudo DEBIAN_FRONTEND=noninteractive apt install --yes git make dotnet8 # workaround for https://github.com/actions/runner/issues/2033 - name: ownership workaround @@ -368,10 +413,12 @@ jobs: dotnet new tool-manifest dotnet tool install fsxc --version ${{ env.FSXC_VERSION }} + # make it work with newer .NET + export DOTNET_ROLL_FORWARD=Major find . -type f -name "*.fsx" | xargs -t -I {} dotnet fsxc {} - linux-vanilla--stockdotnet6-and-newmono: + linux-vanilla--stockdotnet8-and-newmono: runs-on: ubuntu-22.04 container: image: "ubuntu:22.04" @@ -384,7 +431,7 @@ jobs: - name: install sudo run: apt update && apt install --yes sudo - name: install all dependencies - run: sudo DEBIAN_FRONTEND=noninteractive apt install --yes git make dotnet6 + run: sudo DEBIAN_FRONTEND=noninteractive apt install --yes git make dotnet8 - name: install last version of mono (Microsoft APT repositories) run: sudo ./scripts/install_mono_from_microsoft_deb_packages.sh @@ -411,10 +458,12 @@ jobs: dotnet new tool-manifest dotnet tool install fsxc --version ${{ env.FSXC_VERSION }} + # make it work with newer .NET + export DOTNET_ROLL_FORWARD=Major find . -type f -name "*.fsx" | xargs -t -I {} dotnet fsxc {} - linux-vanilla--stockdotnet6-and-stockmono: + linux-vanilla--stockdotnet8-and-stockmono: runs-on: ubuntu-22.04 container: image: "ubuntu:22.04" @@ -427,7 +476,7 @@ jobs: - name: install sudo run: apt update && apt install --yes sudo - name: install all dependencies - run: sudo DEBIAN_FRONTEND=noninteractive apt install --yes git make dotnet6 mono-xbuild fsharp + run: sudo DEBIAN_FRONTEND=noninteractive apt install --yes git make dotnet8 mono-xbuild fsharp - name: install GTK libs (dependency of GTK frontend) run: sudo apt install --yes libgtk2.0-cil-dev # workaround for https://github.com/actions/runner/issues/2033 @@ -453,6 +502,8 @@ jobs: dotnet new tool-manifest dotnet tool install fsxc --version ${{ env.FSXC_VERSION }} + # make it work with newer .NET + export DOTNET_ROLL_FORWARD=Major find . -type f -name "*.fsx" | xargs -t -I {} dotnet fsxc {} @@ -506,15 +557,15 @@ jobs: - linux-github--dotnet-and-newmono - linux-vanilla--stockmono-only - linux-vanilla--newmono-only - - linux-vanilla--stockdotnet6-only - - linux-vanilla--stockdotnet6-and-stockmono - - linux-vanilla--stockdotnet6-and-newmono - - windows--dotnet6-and-legacyFramework + - linux-vanilla--stockdotnet8-only + - linux-vanilla--stockdotnet8-and-stockmono + - linux-vanilla--stockdotnet8-and-newmono + - windows--dotnet8-and-legacyFramework - windows--legacyFramework-only - - windows--dotnet6-only - - macOS--dotnet6-and-mono + - windows--dotnet8-only + - macOS--dotnet8-and-mono - macOS--mono-only - - macOS--dotnet6-only + - macOS--dotnet8-only steps: - uses: actions/checkout@v1 @@ -551,9 +602,7 @@ jobs: steps: - uses: actions/checkout@v1 - name: Install snap tools - run: | - sudo apt update - ./scripts/install_snapcraft.sh + run: ./scripts/install_snapcraft.sh # hack to disable msbuild detection # NOTE: you might think an easier way to do this would be use container:\nimage: ubuntu22.04 and then not install msbuild, @@ -596,9 +645,7 @@ jobs: steps: - uses: actions/checkout@v1 - name: Install snap tools - run: | - sudo apt update - ./scripts/install_snapcraft.sh + run: ./scripts/install_snapcraft.sh # hack to disable msbuild detection # NOTE: you might think an easier way to do this would be use container:\nimage: ubuntu22.04 and then not install msbuild, @@ -636,3 +683,47 @@ jobs: run: | sudo apt update ./scripts/snap_release.sh beta + + snap_alpha: + + needs: + - conventions + + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v1 + - name: Install snap tools + run: ./scripts/install_snapcraft.sh maui + + - name: Setup .NET SDK ${{ env.DotNetVersionForMauiGtk }} + uses: actions/setup-dotnet@v1.7.2 + with: + dotnet-version: ${{ env.DotNetVersionForMauiGtk }} + + - name: Bump snap version + run: | + git submodule foreach git fetch --all && git submodule sync --recursive && git submodule update --init --recursive + dotnet fsi ./scripts/snap_bump.fsx + + - name: Generate snap package + run: ./scripts/snap_build_maui.sh || (cat /home/runner/.local/state/snapcraft/log/*.log && exit 1) + + - name: Install snap + # dangerous because it's a local snap (not one from the SnapStore) + run: sudo snap install --dangerous *.snap + + - name: Test snap + run: gee-maui-preview.geewallet --version + + - uses: actions/upload-artifact@v3 + name: Upload snap package as artifact + with: + name: snap_alpha + path: ./*.snap + + - name: Upload snap package to Snap Store + env: + SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAPCRAFT_LOGIN}} + run: | + sudo apt update + ./scripts/snap_release.sh edge diff --git a/.gitignore b/.gitignore index 8c6982c30..61924dfc1 100644 --- a/.gitignore +++ b/.gitignore @@ -97,3 +97,12 @@ fabric.properties .fake .ionide +# Maui generated code +src/GWallet.Frontend.Maui/WelcomePage.xaml +src/GWallet.Frontend.Maui/WelcomePage2.xaml +src/GWallet.Frontend.Maui/LoadingPage.xaml +src/GWallet.Frontend.Maui/BalancesPage.xaml +src/GWallet.Frontend.Maui/PairingFromPage.xaml +src/GWallet.Frontend.Maui/PairingToPage.xaml +src/GWallet.Frontend.Maui/SendPage.xaml +src/GWallet.Frontend.Maui/ReceivePage.xaml diff --git a/geewallet.sln b/geewallet.sln index 5b13e1b8b..55772d5b0 100644 --- a/geewallet.sln +++ b/geewallet.sln @@ -53,6 +53,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Fsdk", "Fsdk", "{6EE07541-9 EndProject Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "GWallet.Frontend.ConsoleApp", "src\GWallet.Frontend.ConsoleApp\GWallet.Frontend.ConsoleApp.fsproj", "{EFACE810-A402-4673-B8B5-4517E698EACE}" EndProject +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "GWallet.Frontend.Maui", "src\GWallet.Frontend.Maui\GWallet.Frontend.Maui.fsproj", "{CA29AD29-DD6C-48F6-B51E-4B8B4C8D6844}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -306,6 +308,30 @@ Global {EFACE810-A402-4673-B8B5-4517E698EACE}.Release|x64.Build.0 = Release|Any CPU {EFACE810-A402-4673-B8B5-4517E698EACE}.Release|x86.ActiveCfg = Release|Any CPU {EFACE810-A402-4673-B8B5-4517E698EACE}.Release|x86.Build.0 = Release|Any CPU + {CA29AD29-DD6C-48F6-B51E-4B8B4C8D6844}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CA29AD29-DD6C-48F6-B51E-4B8B4C8D6844}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CA29AD29-DD6C-48F6-B51E-4B8B4C8D6844}.Debug|ARM.ActiveCfg = Debug|Any CPU + {CA29AD29-DD6C-48F6-B51E-4B8B4C8D6844}.Debug|ARM.Build.0 = Debug|Any CPU + {CA29AD29-DD6C-48F6-B51E-4B8B4C8D6844}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {CA29AD29-DD6C-48F6-B51E-4B8B4C8D6844}.Debug|iPhone.Build.0 = Debug|Any CPU + {CA29AD29-DD6C-48F6-B51E-4B8B4C8D6844}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {CA29AD29-DD6C-48F6-B51E-4B8B4C8D6844}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {CA29AD29-DD6C-48F6-B51E-4B8B4C8D6844}.Debug|x64.ActiveCfg = Debug|Any CPU + {CA29AD29-DD6C-48F6-B51E-4B8B4C8D6844}.Debug|x64.Build.0 = Debug|Any CPU + {CA29AD29-DD6C-48F6-B51E-4B8B4C8D6844}.Debug|x86.ActiveCfg = Debug|Any CPU + {CA29AD29-DD6C-48F6-B51E-4B8B4C8D6844}.Debug|x86.Build.0 = Debug|Any CPU + {CA29AD29-DD6C-48F6-B51E-4B8B4C8D6844}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CA29AD29-DD6C-48F6-B51E-4B8B4C8D6844}.Release|Any CPU.Build.0 = Release|Any CPU + {CA29AD29-DD6C-48F6-B51E-4B8B4C8D6844}.Release|ARM.ActiveCfg = Release|Any CPU + {CA29AD29-DD6C-48F6-B51E-4B8B4C8D6844}.Release|ARM.Build.0 = Release|Any CPU + {CA29AD29-DD6C-48F6-B51E-4B8B4C8D6844}.Release|iPhone.ActiveCfg = Release|Any CPU + {CA29AD29-DD6C-48F6-B51E-4B8B4C8D6844}.Release|iPhone.Build.0 = Release|Any CPU + {CA29AD29-DD6C-48F6-B51E-4B8B4C8D6844}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {CA29AD29-DD6C-48F6-B51E-4B8B4C8D6844}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {CA29AD29-DD6C-48F6-B51E-4B8B4C8D6844}.Release|x64.ActiveCfg = Release|Any CPU + {CA29AD29-DD6C-48F6-B51E-4B8B4C8D6844}.Release|x64.Build.0 = Release|Any CPU + {CA29AD29-DD6C-48F6-B51E-4B8B4C8D6844}.Release|x86.ActiveCfg = Release|Any CPU + {CA29AD29-DD6C-48F6-B51E-4B8B4C8D6844}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/global-net8.json b/global-net8.json new file mode 100644 index 000000000..b68597cd9 --- /dev/null +++ b/global-net8.json @@ -0,0 +1,6 @@ +{ + "sdk": { + "version": "8.0.0", + "rollForward": "latestMinor" + } +} diff --git a/gwallet.maui.sln b/gwallet.maui.sln new file mode 100644 index 000000000..729ba1294 --- /dev/null +++ b/gwallet.maui.sln @@ -0,0 +1,33 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31611.283 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "GWallet.Frontend.Maui", "src\GWallet.Frontend.Maui\GWallet.Frontend.Maui.fsproj", "{D6C1C0C8-FD57-476F-8A60-BA99D8346045}" +EndProject +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "GWallet.Backend", "src\GWallet.Backend\GWallet.Backend.fsproj", "{DA2EFDCB-1A3B-4057-ADAE-3831DCFA4056}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D6C1C0C8-FD57-476F-8A60-BA99D8346045}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D6C1C0C8-FD57-476F-8A60-BA99D8346045}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D6C1C0C8-FD57-476F-8A60-BA99D8346045}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {D6C1C0C8-FD57-476F-8A60-BA99D8346045}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D6C1C0C8-FD57-476F-8A60-BA99D8346045}.Release|Any CPU.Build.0 = Release|Any CPU + {D6C1C0C8-FD57-476F-8A60-BA99D8346045}.Release|Any CPU.Deploy.0 = Release|Any CPU + {DA2EFDCB-1A3B-4057-ADAE-3831DCFA4056}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DA2EFDCB-1A3B-4057-ADAE-3831DCFA4056}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DA2EFDCB-1A3B-4057-ADAE-3831DCFA4056}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DA2EFDCB-1A3B-4057-ADAE-3831DCFA4056}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {61F7FB11-1E47-470C-91E2-47F8143E1572} + EndGlobalSection +EndGlobal diff --git a/scripts/configure.fsx b/scripts/configure.fsx index 8a9c78159..047912004 100644 --- a/scripts/configure.fsx +++ b/scripts/configure.fsx @@ -3,6 +3,7 @@ open System open System.IO open System.Linq +open System.Text.RegularExpressions #if !LEGACY_FRAMEWORK #r "nuget: Fsdk, Version=0.6.0--date20231031-0834.git-2737eea" @@ -202,9 +203,35 @@ let AddToDefinedConstants (constant: string) (configMap: Map) = configMap |> Map.add configKey (sprintf "%s;%s" previousConstants constant) +// Either maui-* or gtk, as for Maui/Gtk Maui sources are used directly instead of maui-gtk workload +let mauiWorkloads = + match buildTool with + | Some "dotnet" -> + let workloadListResult = + Process + .Execute({ Command = "dotnet"; Arguments = "workload list" }, Echo.All) + .Unwrap("dotnet workload list command failed") + Regex.Matches(workloadListResult, "^(gtk|maui[a-zA-Z0-9\\-]*)", RegexOptions.Multiline).Cast() + |> Seq.map (fun each -> each.Value) + |> Seq.toList + | _ -> List.Empty + +let frontend = + if not (List.isEmpty mauiWorkloads) then + if mauiWorkloads |> List.exists (fun workload -> workload.Contains "gtk") then + "Maui/Gtk" + else + "Maui" + elif areGtkLibsAbsentOrDoesNotApply then + "Console" + else + "Xamarin.Forms" let configFileToBeWritten = - let initialConfigFile = Map.empty.Add("Prefix", prefix.FullName) + let initialConfigFile = + Map.empty + .Add("Prefix", prefix.FullName) + .Add("Frontend", frontend) let configFileStageTwo = match legacyBuildTool with @@ -240,12 +267,9 @@ let version = Misc.GetCurrentVersion(rootDir) let repoInfo = Git.GetRepoInfo() -let frontend = - if areGtkLibsAbsentOrDoesNotApply then - "Console" - else - "Xamarin.Forms" - +if not (List.isEmpty mauiWorkloads) then + let globalJsonFile = "global-net8.json" + File.Copy(globalJsonFile, "global.json") Console.WriteLine() Console.WriteLine(sprintf diff --git a/scripts/geewallet-maui-gtk.sh b/scripts/geewallet-maui-gtk.sh new file mode 100755 index 000000000..6d66682d5 --- /dev/null +++ b/scripts/geewallet-maui-gtk.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +dotnet $SNAP/GWallet.Frontend.Maui.dll "$@" diff --git a/scripts/install_snapcraft.sh b/scripts/install_snapcraft.sh index 9d6d8584a..beb2c2991 100755 --- a/scripts/install_snapcraft.sh +++ b/scripts/install_snapcraft.sh @@ -1,12 +1,18 @@ #!/usr/bin/env bash -set -euxo pipefail +set -exo pipefail + +sudo apt update sudo apt install -y snapd snap version # we can switch to a newer channel when we're ready to upgrade # to use SNAPCRAFT_STORE_CREDENTIALS instead of --with when pushing -sudo snap install --classic --channel=6.x/stable snapcraft +if [ $1 == "maui" ]; then + sudo snap install --classic --channel=7.x/stable snapcraft +else + sudo snap install --classic --channel=6.x/stable snapcraft +fi # workaround for GithubActionsCI+snapcraft, see https://forum.snapcraft.io/t/permissions-problem-using-snapcraft-in-azure-pipelines/13258/14?u=knocte sudo chown root:root / diff --git a/scripts/make.fsx b/scripts/make.fsx index 2b3d5164f..76a8eae28 100644 --- a/scripts/make.fsx +++ b/scripts/make.fsx @@ -27,17 +27,20 @@ let PASCALCASE_NAME = "GWallet" let XF_FRONTEND_LIB = sprintf "%s.Frontend.XF" PASCALCASE_NAME let GTK_FRONTEND_APP = sprintf "%s.Frontend.XF.Gtk" PASCALCASE_NAME +let MAUI_FRONTEND_APP = sprintf "%s.Frontend.Maui" PASCALCASE_NAME let CONSOLE_FRONTEND_APP = sprintf "%s.Frontend.ConsoleApp" PASCALCASE_NAME let BACKEND_LIB = sprintf "%s.Backend" PASCALCASE_NAME type FrontendProject = | XF | Gtk + | Maui member self.GetProjectFile(): FileInfo = let projName = match self with | Gtk -> GTK_FRONTEND_APP | XF -> XF_FRONTEND_LIB + | Maui -> MAUI_FRONTEND_APP let prjFile = let projFileName = sprintf "%s.fsproj" projName @@ -50,14 +53,17 @@ type FrontendProject = type FrontendApp = | Console | Gtk + | Maui member self.GetProjectName() = match self with | Console -> CONSOLE_FRONTEND_APP | Gtk -> GTK_FRONTEND_APP + | Maui -> MAUI_FRONTEND_APP member self.GetExecutableName() = match self with | Console -> CONSOLE_FRONTEND_APP | Gtk -> UNIX_NAME + | Maui -> MAUI_FRONTEND_APP override self.ToString() = sprintf "%A" self @@ -201,6 +207,11 @@ let BuildSolutionOrProject Seq.append ["LEGACY_FRAMEWORK"] defineConstantsFromBuildConfig else defineConstantsFromBuildConfig + let defineConstantsSoFar = + if not(file.FullName.EndsWith "maui.sln") then + Seq.append ["XAMARIN"] defineConstantsSoFar + else + defineConstantsSoFar let allDefineConstants = match maybeConstant with | Some constant -> Seq.append [constant] defineConstantsSoFar @@ -249,9 +260,69 @@ let BuildSolutionOrProject Environment.Exit 1 | _ -> () +// TODO: we have to change this function to be the other way around (i.e. copy from Maui to XF) once we +// have a finished version of Maui and we consider XF as legacy. +let CopyXamlFiles() = + let files = + [| + "WelcomePage.xaml" + "WelcomePage2.xaml" + "LoadingPage.xaml" + "BalancesPage.xaml" + "PairingFromPage.xaml" + "PairingToPage.xaml" + "ReceivePage.xaml" + "SendPage.xaml" + |] + for file in files do + let sourcePath = Path.Combine("src", "GWallet.Frontend.XF", file) + let destPath = Path.Combine("src", "GWallet.Frontend.Maui", file) + + File.Copy(sourcePath, destPath, true) + let fileText = File.ReadAllText(destPath) + File.WriteAllText( + destPath, + fileText + .Replace("http://xamarin.com/schemas/2014/forms","http://schemas.microsoft.com/dotnet/2021/maui") + .Replace("clr-namespace:ZXing.Net.Mobile.Forms;assembly=ZXing.Net.Mobile.Forms","clr-namespace:ZXing.Net.Maui.Controls;assembly=ZXing.Net.MAUI.Controls") + .Replace("GWallet.Frontend.XF", "GWallet.Frontend.Maui") + .Replace("ZXingBarcodeImageView", "BarcodeGeneratorView") + ) + + + +let DotNetBuild + (solutionProjectFileName: string) + (binaryConfig: BinaryConfig) + (args: string) + (ignoreError: bool) + = + let configOption = sprintf "-c %s" (binaryConfig.ToString()) + let buildArgs = (sprintf "build %s %s %s" configOption solutionProjectFileName args) + let buildProcess = Process.Execute ({ Command = "dotnet"; Arguments = buildArgs }, Echo.All) + match buildProcess.Result with + | Error _ -> + if not ignoreError then + Console.WriteLine() + Console.Error.WriteLine "dotnet build failed" +#if LEGACY_FRAMEWORK + PrintNugetVersion() |> ignore +#endif + Environment.Exit 1 + else + () + | _ -> () + +let BuildMauiProject (binaryConfig: BinaryConfig) (frameworkIdentifier: string) = + let mauiProjectFilePath = FrontendProject.Maui.GetProjectFile().FullName + DotNetBuild mauiProjectFilePath binaryConfig (sprintf "--framework %s" frameworkIdentifier) false + let JustBuild binaryConfig maybeConstant: FrontendApp*FileInfo = + CopyXamlFiles() + let maybeBuildTool = Map.tryFind "BuildTool" buildConfigContents let maybeLegacyBuildTool = Map.tryFind "LegacyBuildTool" buildConfigContents + let maybeConfigFrontend = Map.tryFind "Frontend" buildConfigContents let solutionFile = FsxHelper.GetSolution SolutionFile.Default let getBuildToolAndArgs(buildTool: string) = @@ -328,6 +399,13 @@ let JustBuild binaryConfig maybeConstant: FrontendApp*FileInfo = FrontendApp.Console | _ -> FrontendApp.Console + | Some "dotnet", _ when maybeConfigFrontend |> Option.exists (fun value -> value.StartsWith "Maui") -> + if maybeConfigFrontend = Some "Maui/Gtk" then + BuildMauiProject binaryConfig "net8.0-gtk" + else + BuildMauiProject binaryConfig "net8.0-android" + + FrontendApp.Maui | Some buildTool, Some legacyBuildTool when buildTool = "dotnet" && legacyBuildTool = "xbuild" -> if FsxHelper.AreGtkLibsPresent Echo.All then BuildSolutionOrProject @@ -379,7 +457,7 @@ let GetPathToFrontend (frontend: FrontendApp) (binaryConfig: BinaryConfig): Dire "bin", binaryConfig.ToString() #if !LEGACY_FRAMEWORK - , "net6.0" + , "net8.0" #endif ) |> DirectoryInfo diff --git a/scripts/prepare_maui_gtk.sh b/scripts/prepare_maui_gtk.sh new file mode 100755 index 000000000..acf8cff7a --- /dev/null +++ b/scripts/prepare_maui_gtk.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +set -euxo pipefail + +# Install gtk workload +wget -O gtksharp.net.sdk.gtk.manifest-$DotNetVersionForMauiGtk.nupkg https://globalcdn.nuget.org/packages/gtksharp.net.sdk.gtk.manifest-$DotNetVersionForMauiGtk.$GtkSharpVersion.nupkg +DOTNET_DIR=~/.dotnet +WORKLOAD_MANIFEST_DIR=$DOTNET_DIR/sdk-manifests/$DotNetVersionForMauiGtk/gtksharp.net.sdk.gtk +mkdir -p $WORKLOAD_MANIFEST_DIR/ +unzip -j gtksharp.net.sdk.gtk.manifest-$DotNetVersionForMauiGtk.nupkg "data/*" -d $WORKLOAD_MANIFEST_DIR/ +rm gtksharp.net.sdk.gtk.manifest-$DotNetVersionForMauiGtk.nupkg +# otherwise we get System.UnauthorizedAccessException: Access to the path '/home/runner/.dotnet/sdk-manifests/6.0.300/gtksharp.net.sdk.gtk/WorkloadManifest.json' is denied. +chmod 764 $WORKLOAD_MANIFEST_DIR/* +dotnet workload search +dotnet workload install gtk --skip-manifest-update + diff --git a/scripts/sanitycheck.fsx b/scripts/sanitycheck.fsx index 3506ba182..e532580c3 100755 --- a/scripts/sanitycheck.fsx +++ b/scripts/sanitycheck.fsx @@ -92,8 +92,9 @@ let FindOffendingPrintfUsage () = String.Format ( "scripts{0}" + "src{1}GWallet.Frontend.Console{0}" + + "src{1}GWallet.Frontend.Maui{0}" + "src{1}GWallet.Backend.Tests{0}" + - "src{1}GWallet.Backend{1}FSharpUtil.fs", + "src{1}GWallet.Backend{1}FSharpUtil.fs{0}", Path.PathSeparator, Path.DirectorySeparatorChar ) diff --git a/scripts/snap_build_maui.sh b/scripts/snap_build_maui.sh new file mode 100755 index 000000000..2881199dc --- /dev/null +++ b/scripts/snap_build_maui.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash +set -euxo pipefail + +# Install gtk workload and add Maui nuget source +./scripts/prepare_maui_gtk.sh + +# Build GWallet MAUI Gtk project +./configure.sh +make +dotnet build --configuration=Release --framework=net8.0-gtk ./src/GWallet.Frontend.Maui/GWallet.Frontend.Maui.fsproj +dotnet publish --configuration=Release --framework=net8.0-gtk --output=./staging ./src/GWallet.Frontend.Maui/GWallet.Frontend.Maui.fsproj +cp ./scripts/geewallet-maui-gtk.sh ./staging/ + +rm ./snap/snapcraft.yaml +mv ./snap/local/snapcraft_maui.yaml ./snap/snapcraft.yaml + +sudo snapcraft --destructive-mode diff --git a/scripts/snap_release.fsx b/scripts/snap_release.fsx index c45c64b37..e3700df11 100755 --- a/scripts/snap_release.fsx +++ b/scripts/snap_release.fsx @@ -87,14 +87,22 @@ if gitProvider = GitLab then Console.WriteLine "Checking if this is a tag commit..." +let isEdge = + match Misc.FsxOnlyArguments() with + | "edge" :: _ -> true + | _ -> false + let gitTag = match gitProvider with | GitHub -> let tagsPrefix = "refs/tags/" if not (githubRef.StartsWith tagsPrefix) then - Console.WriteLine (sprintf "No tag being set (GITHUB_REF=%s), skipping release." githubRef) - Environment.Exit 0 - githubRef.Substring tagsPrefix.Length + if not isEdge then + Console.WriteLine (sprintf "No tag being set (GITHUB_REF=%s), skipping release." githubRef) + Environment.Exit 0 + None + else + Some(githubRef.Substring tagsPrefix.Length) | GitLab -> let commitHash = Git.GetLastCommit() @@ -103,23 +111,23 @@ let gitTag = failwith "CI_COMMIT_REF_NAME should be available when GitLab: https://docs.gitlab.com/ee/ci/variables/predefined_variables.html" let ciTag = Environment.GetEnvironmentVariable "CI_COMMIT_TAG" - if String.IsNullOrEmpty ciTag then + if String.IsNullOrEmpty ciTag && not isEdge then Console.WriteLine (sprintf "No tag being set (CI_COMMIT_TAG=%s), skipping release." ciTag) Environment.Exit 0 failwith "GitLab not supported at the moment for Snap release process" - ciTag + Some ciTag let channel = - match Misc.FsxOnlyArguments() with - | [ channel ] -> + match Misc.FsxOnlyArguments(), gitTag with + | [ channel ], _ -> channel - | [] -> + | [], Some tag -> - if not (snapFile.FullName.Contains gitTag) then + if not (snapFile.FullName.Contains tag) then failwithf "Git tag (%s) doesn't match version in snap package file name (%s)" - gitTag + tag snapFile.FullName // the 'stable' and 'candidate' channels require 'stable' grade in the yaml @@ -150,16 +158,19 @@ else // this must be a fork, do nothing Console.WriteLine "snapcraft.login file not found in likely GitLab fork repo, skipping log-in" -Console.WriteLine (sprintf "About to start upload of release %s" gitTag) +Console.WriteLine (sprintf "About to start upload of release %s" (gitTag |> Option.defaultValue channel)) let loginMsgAdvice = "There was a problem trying to login with snapcraft, maybe the credentials expired?\r\n" + "If that is the case, install it in the same way as in install_snapcraft.sh and perform 'snapcraft export-login snapcraft.login', then extract the contents of 'snapcraft.login' file" -Process.Execute({ Command = "snapcraft"; Arguments = "login --with snapcraft.login" }, Echo.All) - .Unwrap(loginMsgAdvice) |> ignore +if not isEdge then + Process.Execute({ Command = "snapcraft"; Arguments = "login --with snapcraft.login" }, Echo.All) + .Unwrap(loginMsgAdvice) |> ignore -Console.WriteLine "Login successfull. Upload starting..." + Console.WriteLine "Login sucessful. Upload starting..." +else + Console.WriteLine "Upload starting..." let snapPush = Process.Execute( diff --git a/snap/local/snapcraft_maui.yaml b/snap/local/snapcraft_maui.yaml new file mode 100644 index 000000000..d8cd836bb --- /dev/null +++ b/snap/local/snapcraft_maui.yaml @@ -0,0 +1,45 @@ +name: gee-maui-preview +base: core22 # the base snap is the execution environment for this snap +version: '0.7.445.0' # just for humans, typically '1.2+git' or '1.3.2' +summary: minimalistic cryptocurrency brainwallet # 79 char long summary +description: | + Non-custodial, minimalistic and pragmatist opensource crossplatform + lightweight brainwallet for people that want to hold the most important + cryptocurrencies in the same application with ease & peace of mind. +license: MIT +icon: logo.png + +# grade must be 'stable' (without the quotes) to release into candidate/stable channels +grade: stable +confinement: strict + +layout: + /usr/lib/cli: + symlink: $SNAP/usr/lib/cli + +apps: + geewallet: + extensions: [gnome] + command: bin/geewallet-maui-gtk.sh + plugs: + - network + +parts: + geewallet: + plugin: dump + source: ./staging + organize: + geewallet-maui-gtk.sh: bin/geewallet-maui-gtk.sh + stage-packages: + - dotnet-runtime-8.0 + override-build: | + set -ex + + snapcraftctl build + + mkdir -p $CRAFT_PART_INSTALL/share/themes + mkdir -p $CRAFT_PART_INSTALL/share/icons + mkdir -p $CRAFT_PART_INSTALL/share/sounds + +environment: + XDG_DATA_DIRS: $SNAP/share:$XDG_DATA_DIRS diff --git a/src/GWallet.Backend.Tests/GWallet.Backend.Tests.fsproj b/src/GWallet.Backend.Tests/GWallet.Backend.Tests.fsproj index 7614dd914..b830b50cf 100644 --- a/src/GWallet.Backend.Tests/GWallet.Backend.Tests.fsproj +++ b/src/GWallet.Backend.Tests/GWallet.Backend.Tests.fsproj @@ -1,6 +1,6 @@  - net6.0 + net8.0 false false false diff --git a/src/GWallet.Frontend.ConsoleApp/GWallet.Frontend.ConsoleApp.fsproj b/src/GWallet.Frontend.ConsoleApp/GWallet.Frontend.ConsoleApp.fsproj index 90c28278e..49a4780cf 100644 --- a/src/GWallet.Frontend.ConsoleApp/GWallet.Frontend.ConsoleApp.fsproj +++ b/src/GWallet.Frontend.ConsoleApp/GWallet.Frontend.ConsoleApp.fsproj @@ -1,7 +1,7 @@  Exe - net6.0 + net8.0 diff --git a/src/GWallet.Frontend.Maui/App.xaml b/src/GWallet.Frontend.Maui/App.xaml new file mode 100644 index 000000000..bf7134f3d --- /dev/null +++ b/src/GWallet.Frontend.Maui/App.xaml @@ -0,0 +1,14 @@ + + + + + + + + + + + diff --git a/src/GWallet.Frontend.Maui/App.xaml.fs b/src/GWallet.Frontend.Maui/App.xaml.fs new file mode 100644 index 000000000..5ef93ea9e --- /dev/null +++ b/src/GWallet.Frontend.Maui/App.xaml.fs @@ -0,0 +1,30 @@ +namespace GWallet.Frontend.Maui + +open Microsoft.Maui +open Microsoft.Maui.Controls +open Microsoft.Maui.Controls.Xaml + +type App() as this = + inherit Application() + + do this.LoadFromXaml typeof |> ignore +#if GTK + // Set style here instead of Styles.xml because OnPlatform property doesn't recognize "Gtk" value + do + // Set padding for buttons to be consistent with other platforms as they have padding around buttons by default. + let style = Style(typeof