Homebrew cask
Is your feature request related to a problem? Please describe. Libation is not available on Homebrew. This is very nice to manage updates.
Describe the solution you'd like Add a Homebrew cask.
Describe alternatives you've considered Manual install :(
Additional context I started a Cask. But the brew audit didn't seem to "like" the pre-releases. Also the app is not signed. I searched and saw some comments about the Apple extortion lol What if there was a donation to cover that?
cask "libation" do
arch arm: "arm64", intel: "x64"
version "11.6.2"
sha256 arm: "966a7fd9104248ff266d6a1d84674c39009ba8ed7f1818daec455af2b9d7f6bf",
intel: "7659791b4712aaa24b1e4b47be7567f138f74856f03ea564a278e3d6a9e91adb"
url "https://github.com/rmcrackan/Libation/releases/download/v#{version}/Libation.#{version}-macOS-chardonnay-#{arch}.tgz"
name "Libation"
desc "Libation is a free, open source audible library manager. Decrypt, backup, organize, and search your audible library."
homepage "https://github.com/rmcrackan/Libation"
livecheck do
url :url
regex(/^Libation\.v?(\d+(?:\.\d+)+)-*macOS.*#{arch}.*tgz$/i)
strategy :github_releases do |json, regex|
json.map do |release|
next if release["draft"]
release["assets"]&.map do |asset|
match = asset["name"]&.match(regex)
next if match.blank?
match[1]
end
end.flatten
end
end
auto_updates true
depends_on macos: ">= :catalina"
app "Libation.app"
end
Audit results:
audit for libation: failed
- Version '11.6.2' differs from '11.1.0' retrieved by livecheck.
- Version '11.6.2' differs from '11.1.0' retrieved by livecheck.
- Signature verification failed:
/private/tmp/cask-audit20241205-97988-h9rst4/Libation.app: rejected
macOS on ARM requires software to be signed.
Please contact the upstream developer to let them know they should sign and notarize their software.
- v11.6.2 is a GitHub pre-release.
libation
* Version '11.6.2' differs from '11.1.0' retrieved by livecheck.
* line 8, col 2: Signature verification failed:
/private/tmp/cask-audit20241205-97988-h9rst4/Libation.app: rejected
macOS on ARM requires software to be signed.
Please contact the upstream developer to let them know they should sign and notarize their software.
* line 8, col 2: v11.6.2 is a GitHub pre-release.
Error: 3 problems in 1 cask detected
I created a shell script to update from Github. So I will use that for now.
https://gist.github.com/jfenske89/e1b0d69eb2f9a7f3ef738386bba4d8db
I'll be happy to be the one to push the button if someone else will do the work. For example, I offer docker builds but no part of that was actually done by me and it's not officially supported. This is a community supported feature which I'm happy to offer along side the official apps. If you can do the PRs for the homebrew casks, I can approve them. I love how the community has taken ownership of the increasingly specific technologies which help spread Libation around.
RE Apple's extortion/fee: I'm not opposed to this either with the same stipulations and if there are some people to help fund it. The logistics of this one get ugly since I'm not on a mac. I don't even know how to sign an app for apple. I assume xcode is involved. What really needs to happen is for an actual knowledgeable apple/mac developer to take interest. I don't think simply collecting $99/yr is going to cut it -- I just don't have the tools or knowledge.
I will experiment with some cloud services, such as CircleCI - which might be able to build and sign with a provided key, without the need for a Mac device.
Edit - actually should be able to continue using Github actions, and add a section to the existing build config for signing the MacOS app. Still researching and experimenting...
Need to $ubscribe as an Apple developer first. Then create and download a certificate. Use a guide like this to create a p12 file from that - https://calvium.com/how-to-make-a-p12-file/
Next add some action secrets to the repository:
- CERTIFICATES_P12 (base64 version of the p12 file)
- CERTIFICATES_P12_PASSWORD (password used to create the p12 file)
- APPLE_TEAM_ID (from the Apple Developer account page)
Next update the Github workflow to use https://github.com/Apple-Actions/import-codesign-certs for importing that p12 key.
Afterwards the Scripts/Bundle_MacOS.sh file needs to be updated to run codesign with the key file. It needs to zip the bundle instead of creating a tarball. Then it should notarize and staple the zip file.
I was having issues with this, obviously doing something wrong. This lead to a frustrating day. I will try to pick this up again sometime later.
Thank you very much for funding the apple dev subscription. December is a nutty time for everyone so I'm not going to jump on this immediately. I don't want to start the first subscription year and then watch a month or more slip by because I was too busy to complete these steps.
No problem. There isn't any rush on this. I will have some time to give this another shot. I was hoping this was going to be an easy learning experience for me 😆
Something I might be able to help with, where you stuck?
Something I might be able to help with, where you stuck?
@LeeNX
To be perfectly blunt: this isn't something I want to do; I want someone else to do it. (I don't even know what a homebrew cask is aside from the fact that it's something to do with macos, which I also don't use.) Ideally, that person would do everything themselves that they can (preferably with a PR), and would write explicit step-by-step instructions for the pieces that I must perform myself. Also, I don't intend to add more manual steps to my build habits, so if something needs to be done during every build of Libation, they're going to need to figure out how to create/modify the build workflow to automate it. Oh yeah, and adding documentation to help other mac users know what to do with this.
Other complicating factors: since I don't own a mac, it's possible that I can't run some of the required setup. I also don't have an apple developer subscription -- I have money ear-marked for this purpose though if needed.
In the best case scenario, everything above gets sorted out and this all works and I'd add a disclaimer similar to docker's that it's not officially supported. (Since there's no way for me to do so. Again: no mac) Even with the docker disclaimer, I get tons of docker questions; I'm sure this will be similar.
Sorry if this sounds pissy; I don't intend it to be. It's just that this is other people's nice-to-have which I'll never see any personal benefit from (albeit this would presumably be good for other users) so I'm not in any hurry to carve out time to figure it out. This ticket's author seems very knowledgeable and would likely be a good resource.
@LeeNX I meant to get back to this, but haven't yet. I added a step to sign with an Apple team certificate and "staple" whatever that means lol
I was having issues with the secrets. I am new to Github actions. I tried with "repository secrets" and lastly with a "production" environment that I created in the repository. The secrets seem to be empty no matter what I tried.
Besides that, I don't know if the bundle changes actually work. I am sure someone with $99 to spare and more experience can figure it out faster than me 😂
Required secrets:
- CERTIFICATES_P12
- CERTIFICATES_P12_PASSWORD
- APPLE_TEAM_ID
- APPLE_TEAM_EMAIL
New file, build-mac.yaml (with debugging at the top which should be removed):
# build-mac.yml
# Reusable workflow that builds the MacOS (x64 and arm64) versions of Libation.
---
name: build
on:
workflow_call:
inputs:
version_override:
type: string
description: "Version number override"
required: false
run_unit_tests:
type: boolean
description: "Skip running unit tests"
required: false
default: true
runs_on:
type: string
description: "The GitHub hosted runner to use"
required: true
architecture:
type: string
description: "CPU architecture targeted by the build."
required: true
env:
DOTNET_CONFIGURATION: "Release"
DOTNET_VERSION: "9.0.x"
RELEASE_NAME: "chardonnay"
jobs:
build:
name: "MacOS-${{ inputs.architecture }}"
runs-on: ${{ inputs.runs_on }}
environment: production
steps:
- name: Print environment variables
run: |
echo "DOTNET_CONFIGURATION=${{ env.DOTNET_CONFIGURATION }}"
echo "DOTNET_VERSION=${{ env.DOTNET_VERSION }}"
echo "RELEASE_NAME=${{ env.RELEASE_NAME }}"
echo "CERTIFICATES_P12 length=${#CERTIFICATES_P12}"
echo "CERTIFICATES_P12_PASSWORD length=${#CERTIFICATES_P12_PASSWORD}"
echo "APPLE_TEAM_ID length=${#APPLE_TEAM_ID}"
echo "APPLE_TEAM_EMAIL ${APPLE_TEAM_EMAIL}"
env:
CERTIFICATES_P12: ${{ secrets.CERTIFICATES_P12 }}
CERTIFICATES_P12_PASSWORD: ${{ secrets.CERTIFICATES_P12_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
APPLE_TEAM_EMAIL: ${{ secrets.APPLE_TEAM_EMAIL }}
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: ${{ env.DOTNET_VERSION }}
env:
NUGET_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Import Code-Signing Certificates
uses: apple-actions/import-codesign-certs@v3
with:
p12-file-base64: ${{ secrets.CERTIFICATES_P12 }}
p12-password: ${{ secrets.CERTIFICATES_P12_PASSWORD }}
- name: Get version
id: get_version
run: |
inputVersion="${{ inputs.version_override }}"
if [[ "${#inputVersion}" -gt 0 ]]
then
version="${inputVersion}"
else
version="$(grep -Eio -m 1 '<Version>.*</Version>' ./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
run: dotnet test
- name: Publish
id: publish
working-directory: ./Source
run: |
display_os="macOS"
RUNTIME_ID="osx-${{ inputs.architecture }}"
OUTPUT="bin/Publish/${display_os}-${{ inputs.architecture }}-${{ env.RELEASE_NAME }}"
echo "display_os=${display_os}" >> $GITHUB_OUTPUT
echo "Runtime Identifier: $RUNTIME_ID"
echo "Output Directory: $OUTPUT"
dotnet publish \
LibationAvalonia/LibationAvalonia.csproj \
--runtime $RUNTIME_ID \
--configuration ${{ env.DOTNET_CONFIGURATION }} \
--output $OUTPUT \
-p:PublishProfile=LibationAvalonia/Properties/PublishProfiles/${display_os}Profile.pubxml
dotnet publish \
LoadByOS/${display_os}ConfigApp/${display_os}ConfigApp.csproj \
--runtime $RUNTIME_ID \
--configuration ${{ env.DOTNET_CONFIGURATION }} \
--output $OUTPUT \
-p:PublishProfile=LoadByOS/Properties/${display_os}ConfigApp/PublishProfiles/${display_os}Profile.pubxml
dotnet publish \
LibationCli/LibationCli.csproj \
--runtime $RUNTIME_ID \
--configuration ${{ env.DOTNET_CONFIGURATION }} \
--output $OUTPUT \
-p:PublishProfile=LibationCli/Properties/PublishProfiles/${display_os}Profile.pubxml
dotnet publish \
HangoverAvalonia/HangoverAvalonia.csproj \
--runtime $RUNTIME_ID \
--configuration ${{ env.DOTNET_CONFIGURATION }} \
--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 }}-${{ inputs.architecture }}-${{ env.RELEASE_NAME }}
run: |
BUNDLE_DIR=$(pwd)
echo "Bundle dir: ${BUNDLE_DIR}"
cd ..
SCRIPT=../../../Scripts/Bundle_MacOS.sh
chmod +rx ${SCRIPT}
${SCRIPT} "${BUNDLE_DIR}" "${{ steps.get_version.outputs.version }}" "${{ inputs.architecture }}" "${{ secrets.APPLE_TEAM_ID }}" "${{ secrets.APPLE_TEAM_EMAIL }}"
artifact=$(ls ./bundle)
echo "artifact=${artifact}" >> "${GITHUB_OUTPUT}"
- name: Publish bundle
uses: actions/upload-artifact@v4
with:
name: ${{ steps.bundle.outputs.artifact }}
path: ./Source/bin/Publish/bundle/${{ steps.bundle.outputs.artifact }}
if-no-files-found: error
retention-days: 7
Updated Scripts/Bundle_MacOS.sh (includes debugging that may need to be deleted):
#!/bin/bash
BIN_DIR=$1; shift
VERSION=$1; shift
ARCH=$1; shift
APPLE_TEAM_ID=$1; shift
APPLE_TEAM_EMAIL=$1; shift
if [ -z "$BIN_DIR" ]
then
echo "This script must be called with a the Libation macos 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
if [ -z $APPLE_TEAM_ID ] || [ -z $APPLE_TEAM_EMAIL ]
then
echo "[WARNING] App will fail Gatekeeper verification without valid Apple Team information."
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
BUNDLE=./Libation.app
echo "Bundle dir: $BUNDLE"
if [[ -d $BUNDLE ]]
then
echo "$BUNDLE directory already exists, aborting."
exit
fi
BUNDLE_CONTENTS=$BUNDLE/Contents
echo "Bundle Contents dir: $BUNDLE_CONTENTS"
BUNDLE_RESOURCES=$BUNDLE_CONTENTS/Resources
echo "Resources dir: $BUNDLE_RESOURCES"
BUNDLE_MACOS=$BUNDLE_CONTENTS/MacOS
echo "MacOS dir: $BUNDLE_MACOS"
mkdir -p $BUNDLE_CONTENTS
mkdir -p $BUNDLE_RESOURCES
mkdir -p $BUNDLE_MACOS
mv "${BIN_DIR}/"* $BUNDLE_MACOS
if [ $? -ne 0 ]
then echo "Error moving ${BIN_DIR} files"
exit
fi
echo "Make fileicon executable..."
chmod +x $BUNDLE_MACOS/fileicon
echo "Moving icon..."
mv $BUNDLE_MACOS/libation.icns $BUNDLE_RESOURCES/libation.icns
echo "Moving Info.plist file..."
mv $BUNDLE_MACOS/Info.plist $BUNDLE_CONTENTS/Info.plist
PLIST_ARCH=$(echo $ARCH | sed 's/x64/x86_64/')
echo "Set LSArchitecturePriority to $PLIST_ARCH"
sed -i -e "s/ARCHITECTURE_STRING/$PLIST_ARCH/" $BUNDLE_CONTENTS/Info.plist
echo "Set CFBundleVersion to $VERSION"
sed -i -e "s/VERSION_STRING/$VERSION/" $BUNDLE_CONTENTS/Info.plist
delfiles=( 'libmp3lame.arm64.so' 'libmp3lame.x64.so' 'libmp3lame.x64.dll' 'libmp3lame.x86.dll' 'ffmpegaac.arm64.so' 'ffmpegaac.x64.so' 'ffmpegaac.x64.dll' 'ffmpegaac.x86.dll' 'MacOSConfigApp' 'MacOSConfigApp.deps.json' 'MacOSConfigApp.runtimeconfig.json')
if [[ "$ARCH" == "arm64" ]]
then
delfiles+=('libmp3lame.x64.dylib' 'ffmpegaac.x64.dylib')
mv $BUNDLE_MACOS/ffmpegaac.arm64.dylib $BUNDLE_MACOS/ffmpegaac.dylib
mv $BUNDLE_MACOS/libmp3lame.arm64.dylib $BUNDLE_MACOS/libmp3lame.dylib
else
delfiles+=('libmp3lame.arm64.dylib' 'ffmpegaac.arm64.dylib')
mv $BUNDLE_MACOS/ffmpegaac.x64.dylib $BUNDLE_MACOS/ffmpegaac.dylib
mv $BUNDLE_MACOS/libmp3lame.x64.dylib $BUNDLE_MACOS/libmp3lame.dylib
fi
for n in "${delfiles[@]}"
do
echo "Deleting $n"
rm $BUNDLE_MACOS/$n
done
APP_FILE=Libation.${VERSION}-macOS-chardonnay-${ARCH}.zip
all_identities=$(security find-identity -v -p codesigning)
identity=$(echo ${all_identities} | sed -n 's/.*"\(.*\)".*/\1/p')
if [ "$APPLE_TEAM_ID" != "" ]; then
echo "Signing executables in: $BUNDLE"
# set -e
set -x
codesign --force --deep --sign "${identity}" $BUNDLE
echo "Exit code: $?"
codesign -dv --verbose=4 $BUNDLE
echo "Exit code: $?"
set +x
# set +e
fi
echo "Creating app bundle: $APP_FILE"
zip -r $APP_FILE $BUNDLE
if [ "$APPLE_TEAM_ID" != "" ]; then
echo "Notarizing: $APP_FILE"
# set -e
set -x
# xcrun notarytool submit "${APP_FILE}" --wait --team-id ${APPLE_TEAM_ID}
xcrun notarytool store-credentials --apple-id "${APPLE_TEAM_EMAIL}" --team-id "${APPLE_TEAM_ID}"
echo "Exit code: $?"
xcrun stapler staple "${APP_FILE}"
echo "Exit code: $?"
set +x
# set +e
fi
mkdir bundle
echo "moving to ./bundle/$APP_FILE"
mv $APP_FILE ./bundle/$APP_FILE
rm -r $BUNDLE
echo "Done!"
Thanks @rmcrackan , I totally get it. I feel the same way about Windows ... ;-).
I don't think you been pissy, I think you are been honest and to the point. Who has time to beat around the bush on how little time we have to give away?
I think most people are offering to help, even as little as they can and where they can. I think that is a big thing for FOSS. Not everybody knows everything and if enough people are interested in something, they can pool their knowledge and resources and hopefully get to a point the mass of people want.
My counter offer to this gives me no benefits but there will be an increase in some people expecting support, securing this app with Apple code signing and notarization, should mean that others could not hijack the app for malware and try blame you, because the app would be secured with your Apple credentials.
My initial post was more geared to @jfenske89 , who looked to have something and I did not want to start from scratch. I have some GitHub actions plus Apple code signing and notarization experience and will to spare some time to help where I can.
So, thanks @jfenske89, any reason not to put this into a PR? I think I saw you say that your GitHub journey is new, I can possible help with this and point you to some helpful tutorials, plus you welcome to ask any questions and hopefully either myself or something else might be able to assist. I can move this into a PR and do some testing, but would not want to take all the credit (I think there is a way to co-author/commit PR, but I have not done this myself before - maybe something to learn?)
Two things that I think need to still be addressed, are their funds for the $99 per year Apple Developer Subscription? Second we have not yet got to the homebrew cask setup (I have not done this before, so I don't know what needs to be done here, but would be something worth investigating).
Looking forward to everybody's feedback.
@Mbucari Clearly I'm not actually going to get to this. I thought I would but then -- let's face it, I have no excuse, I just ... didn't. If you want to set this up, I'll be happy to fund it including getting you a year or three of apple developer account if that's helpful. A user above actually paypal-tipped the equiv. of a year of apple dev'er acct which I've kept aside in case I got around to it.
@jfenske89 I got a developer account and I'm trying to make this work, but I'm running into a problem. Specifically:
xcrun notarytool store-credentials --apple-id "${APPLE_TEAM_EMAIL}" --team-id "${APPLE_TEAM_ID}"
Exits with code 138, and
xcrun stapler staple "${APP_FILE}"
Exits with code 66 and says "Stapler is incapable of working with ZIP archive files."
Would you mind looking at my workflow run and seeing if you can figure out what's wrong? https://github.com/Mbucari/Libation/actions/runs/19315790173
The secrets seem to be empty no matter what I tried
Secrets are not passed to reusable workflows by default. To pass secrest, you need to add secrets: inherit
@Mbucari After quick research, I believe my example script back then was incorrect. The bundle needs to be signed, then zipped. The zip file notarized. Then staple the bundle (not the zip).
Here is some documentation: https://developer.apple.com/documentation/security/customizing-the-notarization-workflow
The documentation uses ditto instead of the zip command, and not sure if it matters. Then there are extra commands, but think those are not needed for this project. The basics I think are important: sign, notarize, staple.
I hope that this helps.
I switched to a Framework and using Fedora. Now I don't have to deal with these complications anymore 😂
@Mbucari and @jfenske89 - Notes from past projects that I have done something similar.
If I remember correctly, you can't codesign the archive, but you must codesign all the files in the archive and then notarytool the archive. You can't staple an archive, only staple dmg and pkg packages.
They way I have done this in past projects, is just add a step in the workflow, if the secrets are in place, then it will run the codesign process, something like ...
- name: Build the macOS Archive and code-sign
if: ${{ ( startsWith(runner.os,'macOS') ) && ( env.MACOS_NOTARIZE_USERNAME != '' ) }}
continue-on-error: true
@jfenske89 @LeeNX I don't have a cask, but I think I have something better: a signed, notarized, and stapled dmg. Find it on my fork's release.
Now the only question is what to do about automatic updates. There's really no way to make existing copies of Libation auto-update to the DMG. Maybe offer BOTH a dmg and a tarball (previous method) for at least some amount of time?
Regarding the cask... I really don't want to do that. At least right now. The process up to this point has been so difficult, and I want to release what I have.
@jfenske89 @LeeNX I don't have a cask, but I think I have something better: a signed, notarized, and stapled dmg. Find it on my fork's release.
Now the only question is what to do about automatic updates. There's really no way to make existing copies of Libation auto-update to the DMG. Maybe offer BOTH a dmg and a tarball (previous method) for at least _some_ amount of time?
Regarding the cask... I really don't want to do that. At least right now. The process up to this point has been so difficult, and I want to release what I have.
If you need something tested, I was able to spin up a Hackintosh VM when I was adding MacOS support to DockSTARTer.
@CLHatch no thanks, I'm good. This is a very much all or nothing process. It either works flawlessly or doesn't work at all.
@jfenske89 Can we close this issue? We didn't make a cask, but we have signed install images now. Is that satisfactory?
If we have signed images now, I'm happy to contribute a cask ...
Please go for it, @max-horvath. And thanks!
Thanks guys!
Again: I don't know anything about casks. Please let us know what to update in the linux docs
Thanks guys!
Again: I don't know anything about casks. Please let us know what to update in the linux docs
I played around with homebrew when I added macOS support to DockSTARTer. Going by what I learned, most likely libation will be able to be installed by typing brew install --cask libation.
@CLHatch , @jfenske89 : Should I just add the following to the bottom of the linux page
Homebrew Cask
brew install --cask libation
Thanks to jfenske89 for taking care of Cask package maintenance.
Hi,
when I do brew search libation on Mac it doesn't find it.
Hi, when I do
brew search libationon Mac it doesn't find it.
I was just guessing on how it would work, honestly. If it does work, possibly you need to do a brew tap command to add the "tap" to get Libation from? I'm not sure how they have it set up for Libation.
Now the only question is what to do about automatic updates. There's really no way to make existing copies of Libation auto-update to the DMG. Maybe offer BOTH a dmg and a tarball (previous method) for at least _some_ amount of time?