diff --git a/.github/workflows/build-linux.yml b/.github/workflows/build-linux.yml
index 3f3a8fd0..86468524 100644
--- a/.github/workflows/build-linux.yml
+++ b/.github/workflows/build-linux.yml
@@ -15,6 +15,21 @@ on:
description: 'Skip running unit tests'
required: false
default: true
+ runs_on:
+ type: string
+ description: 'The GitHub hosted runner to use'
+ required: true
+ OS:
+ type: string
+ description: >
+ The operating system targeted by the build.
+
+ There must be a corresponding Bundle_$OS.sh script file in ./Scripts
+ required: true
+ architecture:
+ type: string
+ description: 'CPU architecture targeted by the build.'
+ required: true
env:
DOTNET_CONFIGURATION: 'Release'
@@ -23,11 +38,8 @@ env:
jobs:
build:
- runs-on: ${{ matrix.os }}
- strategy:
- matrix:
- os: [ubuntu-latest, macos-latest]
- arch: [x64, arm64]
+ name: '${{ inputs.OS }}-${{ inputs.architecture }}'
+ runs-on: ${{ inputs.runs_on }}
steps:
- uses: actions/checkout@v3
- name: Setup .NET
@@ -48,6 +60,7 @@ jobs:
version="$(grep -Eio -m 1 '.*' ./Source/AppScaffolding/AppScaffolding.csproj | sed -r 's/<\/?Version>//g')"
fi
echo "version=${version}" >> "${GITHUB_OUTPUT}"
+
- name: Unit test
if: ${{ inputs.run_unit_tests }}
working-directory: ./Source
@@ -56,52 +69,64 @@ jobs:
- name: Publish
id: publish
working-directory: ./Source
- run: |
- os=${{ matrix.os }}
- target_os="$(echo ${os/-latest/} | sed 's/ubuntu/linux/')"
- display_os="$(echo ${target_os/macos/macOS} | sed 's/linux/Linux/')"
+ run: |
+ if [[ "${{ inputs.OS }}" == "MacOS" ]]
+ then
+ display_os="macOS"
+ RUNTIME_ID="osx-${{ inputs.architecture }}"
+ else
+ display_os="Linux"
+ RUNTIME_ID="linux-${{ inputs.architecture }}"
+ fi
+
+ OUTPUT="bin/Publish/${display_os}-${{ inputs.architecture }}-${{ env.RELEASE_NAME }}"
+
echo "display_os=${display_os}" >> $GITHUB_OUTPUT
- RUNTIME_IDENTIFIER="$(echo ${target_os/macos/osx})-${{ matrix.arch }}"
- echo "$RUNTIME_IDENTIFIER"
+ echo "Runtime Identifier: $RUNTIME_ID"
+ echo "Output Directory: $OUTPUT"
+
dotnet publish \
LibationAvalonia/LibationAvalonia.csproj \
- --runtime "$RUNTIME_IDENTIFIER" \
+ --runtime $RUNTIME_ID \
--configuration ${{ env.DOTNET_CONFIGURATION }} \
- --output bin/Publish/${display_os}-${{ matrix.arch }}-${{ env.RELEASE_NAME }} \
+ --output $OUTPUT \
-p:PublishProfile=LibationAvalonia/Properties/PublishProfiles/${display_os}Profile.pubxml
dotnet publish \
LoadByOS/${display_os}ConfigApp/${display_os}ConfigApp.csproj \
- --runtime "$RUNTIME_IDENTIFIER" \
+ --runtime $RUNTIME_ID \
--configuration ${{ env.DOTNET_CONFIGURATION }} \
- --output bin/Publish/${display_os}-${{ matrix.arch }}-${{ env.RELEASE_NAME }} \
+ --output $OUTPUT \
-p:PublishProfile=LoadByOS/Properties/${display_os}ConfigApp/PublishProfiles/${display_os}Profile.pubxml
dotnet publish \
LibationCli/LibationCli.csproj \
- --runtime "$RUNTIME_IDENTIFIER" \
+ --runtime $RUNTIME_ID \
--configuration ${{ env.DOTNET_CONFIGURATION }} \
- --output bin/Publish/${display_os}-${{ matrix.arch }}-${{ env.RELEASE_NAME }} \
+ --output $OUTPUT \
-p:PublishProfile=LibationCli/Properties/PublishProfiles/${display_os}Profile.pubxml
dotnet publish \
HangoverAvalonia/HangoverAvalonia.csproj \
- --runtime "$RUNTIME_IDENTIFIER" \
+ --runtime $RUNTIME_ID \
--configuration ${{ env.DOTNET_CONFIGURATION }} \
- --output bin/Publish/${display_os}-${{ matrix.arch }}-${{ env.RELEASE_NAME }} \
+ --output $OUTPUT \
-p:PublishProfile=HangoverAvalonia/Properties/PublishProfiles/${display_os}Profile.pubxml
+
- name: Build bundle
id: bundle
- working-directory: ./Source/bin/Publish/${{ steps.publish.outputs.display_os }}-${{ matrix.arch }}-${{ env.RELEASE_NAME }}
+ working-directory: ./Source/bin/Publish/${{ steps.publish.outputs.display_os }}-${{ inputs.architecture }}-${{ env.RELEASE_NAME }}
run: |
BUNDLE_DIR=$(pwd)
echo "Bundle dir: ${BUNDLE_DIR}"
cd ..
- SCRIPT=../../../Scripts/Bundle_${{ steps.publish.outputs.display_os }}.sh
+ SCRIPT=../../../Scripts/Bundle_${{ inputs.OS }}.sh
chmod +rx ${SCRIPT}
- ${SCRIPT} "${BUNDLE_DIR}" "${{ steps.get_version.outputs.version }}" "${{ matrix.arch }}"
+ ${SCRIPT} "${BUNDLE_DIR}" "${{ steps.get_version.outputs.version }}" "${{ inputs.architecture }}"
artifact=$(ls ./bundle)
echo "artifact=${artifact}" >> "${GITHUB_OUTPUT}"
+
- name: Publish bundle
uses: actions/upload-artifact@v3
with:
name: ${{ steps.bundle.outputs.artifact }}
path: ./Source/bin/Publish/bundle/${{ steps.bundle.outputs.artifact }}
- if-no-files-found: error
\ No newline at end of file
+ if-no-files-found: error
+ retention-days: 7
diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml
index 605016a1..a14c5a38 100644
--- a/.github/workflows/build-windows.yml
+++ b/.github/workflows/build-windows.yml
@@ -22,6 +22,7 @@ env:
jobs:
build:
+ name: '${{ matrix.os }}-${{ matrix.release_name }}'
runs-on: windows-latest
strategy:
matrix:
@@ -110,4 +111,4 @@ jobs:
name: ${{ steps.zip.outputs.artifact }}.zip
path: ./Source/bin/Publish/${{ steps.zip.outputs.artifact }}.zip
if-no-files-found: error
-
+ retention-days: 7
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index b6cf9787..ce1186ac 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -17,14 +17,34 @@ on:
default: true
jobs:
+
windows:
uses: ./.github/workflows/build-windows.yml
with:
version_override: ${{ inputs.version_override }}
run_unit_tests: ${{ inputs.run_unit_tests }}
-
+
linux:
+ strategy:
+ matrix:
+ OS: [Redhat, Debian]
+ architecture: [x64, arm64]
uses: ./.github/workflows/build-linux.yml
with:
version_override: ${{ inputs.version_override }}
+ runs_on: ubuntu-latest
+ OS: ${{ matrix.OS }}
+ architecture: ${{ matrix.architecture }}
+ run_unit_tests: ${{ inputs.run_unit_tests }}
+
+ macos:
+ strategy:
+ matrix:
+ architecture: [x64, arm64]
+ uses: ./.github/workflows/build-linux.yml
+ with:
+ version_override: ${{ inputs.version_override }}
+ runs_on: macos-latest
+ OS: MacOS
+ architecture: ${{ matrix.architecture }}
run_unit_tests: ${{ inputs.run_unit_tests }}
diff --git a/.releaseindex.json b/.releaseindex.json
index 5e44f230..9d9dea23 100644
--- a/.releaseindex.json
+++ b/.releaseindex.json
@@ -1,8 +1,10 @@
{
- "WindowsClassic": "Classic-Libation\\.\\d+\\.\\d+\\.\\d+-win(dows)?-classic\\.zip",
- "WindowsAvalonia": "Libation\\.\\d+\\.\\d+\\.\\d+-win(dows)?-chardonnay\\.zip",
- "LinuxAvalonia": "Libation\\.\\d+\\.\\d+\\.\\d+-linux-chardonnay-amd64\\.deb",
- "MacOSAvalonia": "Libation\\.\\d+\\.\\d+\\.\\d+-macOS-chardonnay-x64\\.tgz",
- "LinuxAvalonia_Arm64": "Libation\\.\\d+\\.\\d+\\.\\d+-linux-chardonnay-arm64\\.deb",
- "MacOSAvalonia_Arm64": "Libation\\.\\d+\\.\\d+\\.\\d+-macOS-chardonnay-arm64\\.tgz"
+ "WindowsClassic": "Classic-Libation\\.\\d+\\.\\d+\\.\\d+-win(dows)?-classic\\.zip",
+ "WindowsAvalonia": "Libation\\.\\d+\\.\\d+\\.\\d+-win(dows)?-chardonnay\\.zip",
+ "LinuxAvalonia": "Libation\\.\\d+\\.\\d+\\.\\d+-linux-chardonnay-amd64\\.deb",
+ "LinuxAvalonia_RPM": "Libation\\.\\d+\\.\\d+\\.\\d+-linux-chardonnay-amd64\\.rpm",
+ "MacOSAvalonia": "Libation\\.\\d+\\.\\d+\\.\\d+-macOS-chardonnay-x64\\.tgz",
+ "LinuxAvalonia_Arm64": "Libation\\.\\d+\\.\\d+\\.\\d+-linux-chardonnay-arm64\\.deb",
+ "LinuxAvalonia_Arm64_RPM": "Libation\\.\\d+\\.\\d+\\.\\d+-linux-chardonnay-arm64\\.rpm",
+ "MacOSAvalonia_Arm64": "Libation\\.\\d+\\.\\d+\\.\\d+-macOS-chardonnay-arm64\\.tgz"
}
diff --git a/Scripts/Bundle_Linux.sh b/Scripts/Bundle_Debian.sh
similarity index 100%
rename from Scripts/Bundle_Linux.sh
rename to Scripts/Bundle_Debian.sh
diff --git a/Scripts/Bundle_Redhat.sh b/Scripts/Bundle_Redhat.sh
new file mode 100644
index 00000000..77bb4769
--- /dev/null
+++ b/Scripts/Bundle_Redhat.sh
@@ -0,0 +1,140 @@
+#!/bin/bash
+
+BIN_DIR=$1; shift
+VERSION=$1; shift
+ARCH=$1; shift
+
+if [ -z "$BIN_DIR" ]
+then
+ echo "This script must be called with a the Libation Linux bins directory as an argument."
+ exit
+fi
+
+if [ ! -d "$BIN_DIR" ]
+then
+ echo "The directory \"$BIN_DIR\" does not exist."
+ exit
+fi
+
+if [ -z "$VERSION" ]
+then
+ echo "This script must be called with the Libation version number as an argument."
+ exit
+fi
+
+if [ -z "$ARCH" ]
+then
+ echo "This script must be called with the Libation cpu architecture as an argument."
+ exit
+fi
+
+contains() { case "$1" in *"$2"*) true ;; *) false ;; esac }
+
+if ! contains "$BIN_DIR" "$ARCH"
+then
+ echo "This script must be called with a Libation binaries for ${ARCH}."
+ exit
+fi
+
+BASEDIR=$(pwd)
+
+delfiles=('libmp3lame.arm64.dylib' 'libmp3lame.x64.dylib' 'libmp3lame.x64.dll' 'libmp3lame.x86.dll' 'ffmpegaac.arm64.dylib' 'ffmpegaac.x64.dylib' 'ffmpegaac.x64.dll' 'ffmpegaac.x86.dll' 'LinuxConfigApp' 'LinuxConfigApp.deps.json' 'LinuxConfigApp.runtimeconfig.json')
+if [[ "$ARCH" == "x64" ]]
+then
+ delfiles+=('libmp3lame.arm64.so' 'ffmpegaac.arm64.so')
+ ARCH_RPM="x86_64"
+ ARCH="amd64"
+else
+ delfiles+=('libmp3lame.x64.so' 'ffmpegaac.x64.so')
+ ARCH_RPM="aarch64"
+fi
+
+notinstalled=('libcoreclrtraceptprovider.so' 'libation_glass.svg' 'Libation.desktop')
+
+mkdir -p ~/rpmbuild/SPECS
+mkdir ~/rpmbuild/BUILD
+mkdir ~/rpmbuild/RPMS
+
+echo "Name: libation
+Version: ${VERSION}
+Release: 1
+Summary: Liberate your Audible Library
+
+License: GPLv3+
+URL: https://github.com/rmcrackan/Libation
+Source0: https://github.com/rmcrackan/Libation
+
+Requires: bash
+
+
+%define __os_install_post %{nil}
+
+%description
+Liberate your Audible Library
+
+%install
+mkdir -p %{buildroot}%{_libdir}/%{name}
+mkdir -p %{buildroot}%{_datadir}/icons/hicolor/scalable/apps
+mkdir -p %{buildroot}%{_datadir}/applications
+
+if test -f 'libcoreclrtraceptprovider.so'; then
+ rm 'libcoreclrtraceptprovider.so'
+fi
+
+touch appsettings.json
+chmod 666 appsettings.json
+
+install -m 666 libation_glass.svg %{buildroot}%{_datadir}/icons/hicolor/scalable/apps/libation.svg
+install -m 666 Libation.desktop %{buildroot}%{_datadir}/applications/Libation.desktop
+
+rm libation_glass.svg
+rm Libation.desktop
+
+install * %{buildroot}%{_libdir}/%{name}/
+
+%post
+
+ln -s %{_libdir}/%{name}/Libation %{_bindir}/libation
+ln -s %{_libdir}/%{name}/Hangover %{_bindir}/hangover
+ln -s %{_libdir}/%{name}/LibationCli %{_bindir}/libationcli
+
+gtk-update-icon-cache -f %{_datadir}/icons/hicolor/
+
+%postun
+
+rm %{_bindir}/libation
+rm %{_bindir}/hangover
+rm %{_bindir}/libationcli
+
+if ! grep -q 'fs.inotify.max_user_instances=524288' /etc/sysctl.conf; then
+ echo fs.inotify.max_user_instances=524288 | tee -a /etc/sysctl.conf && sysctl -p
+fi
+
+%files
+%{_datadir}/icons/hicolor/scalable/apps/libation.svg
+%{_datadir}/applications/Libation.desktop
+%{_libdir}/%{name}/appsettings.json" >> ~/rpmbuild/SPECS/libation.spec
+
+
+cd "$BIN_DIR"
+
+for f in *; do
+ if [[ " ${delfiles[*]} " =~ " ${f} " ]]; then
+ echo "Deleting $f"
+ elif [[ ! " ${notinstalled[*]} " =~ " ${f} " ]]; then
+ echo "%{_libdir}/%{name}/${f}" >> ~/rpmbuild/SPECS/libation.spec
+ cp $f ~/rpmbuild/BUILD/
+ else
+ cp $f ~/rpmbuild/BUILD/
+ fi
+done
+
+cd ~/rpmbuild/SPECS/
+rpmbuild -bb --target $ARCH_RPM libation.spec
+
+cd $BASEDIR
+RPM_FILE=$(ls ~/rpmbuild/RPMS/${ARCH_RPM})
+
+mkdir bundle
+
+mv ~/rpmbuild/RPMS/${ARCH_RPM}/$RPM_FILE "./bundle/Libation.${VERSION}-linux-chardonnay-${ARCH}.rpm"
diff --git a/Source/AppScaffolding/LibationScaffolding.cs b/Source/AppScaffolding/LibationScaffolding.cs
index efaaf63b..a0b1d9c9 100644
--- a/Source/AppScaffolding/LibationScaffolding.cs
+++ b/Source/AppScaffolding/LibationScaffolding.cs
@@ -330,7 +330,18 @@ namespace AppScaffolding
//Download the release index
var bts = await gitHubClient.Repository.Content.GetRawContent(ownerAccount, repoName, ".releaseindex.json");
var releaseIndex = JObject.Parse(System.Text.Encoding.ASCII.GetString(bts));
- var regexPattern = releaseIndex.Value(ReleaseIdentifier.ToString());
+
+ string regexPattern;
+
+ try
+ {
+ regexPattern = releaseIndex.Value(InteropFactory.Create().ReleaseIdentifier);
+ }
+ catch
+ {
+ regexPattern = releaseIndex.Value(ReleaseIdentifier.ToString());
+ }
+
var regex = new System.Text.RegularExpressions.Regex(regexPattern, System.Text.RegularExpressions.RegexOptions.IgnoreCase);
//https://docs.github.com/en/rest/releases/releases?apiVersion=2022-11-28#get-the-latest-release
diff --git a/Source/LibationFileManager/IInteropFunctions.cs b/Source/LibationFileManager/IInteropFunctions.cs
index 7b0df53c..4ec5a896 100644
--- a/Source/LibationFileManager/IInteropFunctions.cs
+++ b/Source/LibationFileManager/IInteropFunctions.cs
@@ -16,6 +16,7 @@ namespace LibationFileManager
Process RunAsRoot(string exe, string args);
void InstallUpgrade(string upgradeBundle);
bool CanUpgrade { get; }
+ string ReleaseIdentifier { get; }
}
public class WebViewNavigationEventArgs : EventArgs
diff --git a/Source/LibationFileManager/NullInteropFunctions.cs b/Source/LibationFileManager/NullInteropFunctions.cs
index aba0b46f..5bab7361 100644
--- a/Source/LibationFileManager/NullInteropFunctions.cs
+++ b/Source/LibationFileManager/NullInteropFunctions.cs
@@ -15,6 +15,7 @@ namespace LibationFileManager
public void SetFolderIcon(string image, string directory) => throw new PlatformNotSupportedException();
public void DeleteFolderIcon(string directory) => throw new PlatformNotSupportedException();
public bool CanUpgrade => throw new PlatformNotSupportedException();
+ public string ReleaseIdentifier => throw new PlatformNotSupportedException();
public Process RunAsRoot(string exe, string args) => throw new PlatformNotSupportedException();
public void InstallUpgrade(string updateBundle) => throw new PlatformNotSupportedException();
}
diff --git a/Source/LoadByOS/LinuxConfigApp/LinuxInterop.cs b/Source/LoadByOS/LinuxConfigApp/LinuxInterop.cs
index d3d76482..988a3309 100644
--- a/Source/LoadByOS/LinuxConfigApp/LinuxInterop.cs
+++ b/Source/LoadByOS/LinuxConfigApp/LinuxInterop.cs
@@ -1,4 +1,5 @@
-using LibationFileManager;
+using AppScaffolding;
+using LibationFileManager;
using System.Diagnostics;
namespace LinuxConfigApp
@@ -24,6 +25,8 @@ namespace LinuxConfigApp
public void SetFolderIcon(string image, string directory) => throw new PlatformNotSupportedException();
public void DeleteFolderIcon(string directory) => throw new PlatformNotSupportedException();
+ public string ReleaseIdentifier => LibationScaffolding.ReleaseIdentifier.ToString() + (File.Exists("/bin/yum") ? "_RPM" : "");
+
//only run the auto upgrader if the current app was installed from the
//.deb package. Try to detect this by checking if the symlink exists.
public bool CanUpgrade => Directory.Exists("/usr/lib/libation");
diff --git a/Source/LoadByOS/MacOSConfigApp/MacOSInterop.cs b/Source/LoadByOS/MacOSConfigApp/MacOSInterop.cs
index 0cc75660..e7ca21ef 100644
--- a/Source/LoadByOS/MacOSConfigApp/MacOSInterop.cs
+++ b/Source/LoadByOS/MacOSConfigApp/MacOSInterop.cs
@@ -24,6 +24,8 @@ namespace MacOSConfigApp
//the running process, so don't upgrade unless it's "installed" in /Applications
public bool CanUpgrade => Directory.Exists(AppPath);
+ public string ReleaseIdentifier => AppScaffolding.LibationScaffolding.ReleaseIdentifier.ToString();
+
public void InstallUpgrade(string upgradeBundle)
{
Serilog.Log.Information($"Extracting upgrade bundle to {AppPath}");
diff --git a/Source/LoadByOS/WindowsConfigApp/WinInterop.cs b/Source/LoadByOS/WindowsConfigApp/WinInterop.cs
index bf8eae77..d99f3cb6 100644
--- a/Source/LoadByOS/WindowsConfigApp/WinInterop.cs
+++ b/Source/LoadByOS/WindowsConfigApp/WinInterop.cs
@@ -25,6 +25,9 @@ namespace WindowsConfigApp
=> new DirectoryInfo(directory)?.DeleteIcon();
public bool CanUpgrade => true;
+
+ public string ReleaseIdentifier => AppScaffolding.LibationScaffolding.ReleaseIdentifier.ToString();
+
public void InstallUpgrade(string upgradeBundle)
{
var thisExe = Environment.ProcessPath;