Skip to content

Commit

Permalink
Use sparkle framework for auto-updates
Browse files Browse the repository at this point in the history
  • Loading branch information
mr-pennyworth committed Jul 8, 2024
1 parent 68985d0 commit 1096028
Show file tree
Hide file tree
Showing 6 changed files with 147 additions and 28 deletions.
53 changes: 36 additions & 17 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,14 @@ jobs:
- name: Xcode version
run: /usr/bin/xcodebuild -version

- name: Get Previous Tag
run: echo "PREVIOUS_TAG=$(git describe --tags --abbrev=0)" >> $GITHUB_ENV

- name: Get App Version
id: get_version
run: echo "APP_VERSION=$(xcodebuild -showBuildSettings | grep MARKETING_VERSION | cut -f2 -d = | tr -d '[:space:]')" >> $GITHUB_ENV

- name: Check if tag exists
id: check_tag
run: |
if git rev-parse "refs/tags/${{ env.APP_VERSION }}" >/dev/null 2>&1; then
echo "TAG_EXISTS=true" >> $GITHUB_ENV
else
echo "TAG_EXISTS=false" >> $GITHUB_ENV
fi
- name: Get commit messages since last release
if: env.TAG_EXISTS == 'false'
if: env.PREVIOUS_TAG != env.APP_VERSION
run: |
LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
if [ -z "$LAST_TAG" ]; then
Expand All @@ -47,7 +40,7 @@ jobs:
- name: Create Release
id: create_release
if: env.TAG_EXISTS == 'false'
if: env.PREVIOUS_TAG != env.APP_VERSION
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Expand All @@ -61,19 +54,45 @@ jobs:
prerelease: false

- name: Build App
if: env.TAG_EXISTS == 'false'
run: xcodebuild -project AlfredExtraPane.xcodeproj -configuration Release -scheme AlfredExtraPane -derivedDataPath DerivedData build
if: env.PREVIOUS_TAG != env.APP_VERSION
# Don't code sign as sparkle complains that the signature is corrupt.
# At this moment, we don't see any value in figuring out how exactly
# the code signature is corrupt.
run: xcodebuild -project AlfredExtraPane.xcodeproj -configuration Release -scheme AlfredExtraPane -derivedDataPath DerivedData clean build CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO

- name: Copy Built App
if: env.TAG_EXISTS == 'false'
if: env.PREVIOUS_TAG != env.APP_VERSION
run: cp -r DerivedData/Build/Products/Release/AlfredExtraPane.app ./

- name: Zip App
if: env.TAG_EXISTS == 'false'
if: env.PREVIOUS_TAG != env.APP_VERSION
run: zip -r AlfredExtraPane.app.zip AlfredExtraPane.app

- name: Get Sparkle Private Signing Key
if: env.PREVIOUS_TAG != env.APP_VERSION
env:
SPARKLE_PRIVATE_SIGNING_KEY: ${{ secrets.SPARKLE_PRIVATE_SIGNING_KEY }}
run: |
echo "$SPARKLE_PRIVATE_SIGNING_KEY" > sparkle_private_signing.key
- name: Generate Appcast XML
if: env.PREVIOUS_TAG != env.APP_VERSION
run: bash gen-appcast.sh "$APP_VERSION" "$PREVIOUS_TAG" sparkle_private_signing.key

- name: Upload Appcast XML
if: env.PREVIOUS_TAG != env.APP_VERSION
id: upload-appcast-xml
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./appcast.xml
asset_name: appcast.xml
asset_content_type: application/xml

- name: Upload Release Asset
if: env.TAG_EXISTS == 'false'
if: env.PREVIOUS_TAG != env.APP_VERSION
id: upload-release-asset
uses: actions/upload-release-asset@v1
env:
Expand Down
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@ DerivedData
xcuserdata/
xcuserdata
xcuserdata/
Sparkle/
*.key
*.pyc
*.xcworkspace
.idea
.latest-tag
.release-version
AlfredExtraPane.app.zip
appcast.xml
.DS_Store
21 changes: 19 additions & 2 deletions AlfredExtraPane.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
D08B6EE5266F31790099EB36 /* Pane.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08B6EE4266F31790099EB36 /* Pane.swift */; };
D08B6EE7266F9B520099EB36 /* PanePositionCodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08B6EE6266F9B520099EB36 /* PanePositionCodable.swift */; };
D0B3E0A42B8A1F3A008EA695 /* AlfredExtraPaneTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0B3E0A32B8A1F3A008EA695 /* AlfredExtraPaneTests.swift */; };
D0E764282C3C1E6D00E662F3 /* Sparkle in Frameworks */ = {isa = PBXBuildFile; productRef = D0E764272C3C1E6D00E662F3 /* Sparkle */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -69,6 +70,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
D0E764282C3C1E6D00E662F3 /* Sparkle in Frameworks */,
D040E2422667A4FC00495B2D /* Alfred in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -154,6 +156,7 @@
name = AlfredExtraPane;
packageProductDependencies = (
D040E2412667A4FC00495B2D /* Alfred */,
D0E764272C3C1E6D00E662F3 /* Sparkle */,
);
productName = AlfredExtraPane;
productReference = D03EA8CF25551E0400D3656E /* AlfredExtraPane.app */;
Expand Down Expand Up @@ -207,6 +210,7 @@
mainGroup = D03EA8C625551E0400D3656E;
packageReferences = (
D040E2402667A4FC00495B2D /* XCRemoteSwiftPackageReference "AlfredSwift" */,
D0E764262C3C1E6D00E662F3 /* XCRemoteSwiftPackageReference "Sparkle" */,
);
productRefGroup = D03EA8D025551E0400D3656E /* Products */;
projectDirPath = "";
Expand Down Expand Up @@ -397,8 +401,8 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 11.0;
MARKETING_VERSION = 0.1.8;
ONLY_ACTIVE_ARCH = NO;
MARKETING_VERSION = 0.1.7;
OTHER_CODE_SIGN_FLAGS = "--deep";
PRODUCT_BUNDLE_IDENTIFIER = mr.pennyworth.AlfredExtraPane;
PRODUCT_NAME = "$(TARGET_NAME)";
Expand All @@ -418,8 +422,8 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 11.0;
MARKETING_VERSION = 0.1.8;
ONLY_ACTIVE_ARCH = NO;
MARKETING_VERSION = 0.1.7;
OTHER_CODE_SIGN_FLAGS = "--deep";
PRODUCT_BUNDLE_IDENTIFIER = mr.pennyworth.AlfredExtraPane;
PRODUCT_NAME = "$(TARGET_NAME)";
Expand Down Expand Up @@ -513,6 +517,14 @@
minimumVersion = 0.1.9;
};
};
D0E764262C3C1E6D00E662F3 /* XCRemoteSwiftPackageReference "Sparkle" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/sparkle-project/Sparkle";
requirement = {
kind = exactVersion;
version = 2.6.4;
};
};
/* End XCRemoteSwiftPackageReference section */

/* Begin XCSwiftPackageProductDependency section */
Expand All @@ -521,6 +533,11 @@
package = D040E2402667A4FC00495B2D /* XCRemoteSwiftPackageReference "AlfredSwift" */;
productName = Alfred;
};
D0E764272C3C1E6D00E662F3 /* Sparkle */ = {
isa = XCSwiftPackageProductDependency;
package = D0E764262C3C1E6D00E662F3 /* XCRemoteSwiftPackageReference "Sparkle" */;
productName = Sparkle;
};
/* End XCSwiftPackageProductDependency section */
};
rootObject = D03EA8C725551E0400D3656E /* Project object */;
Expand Down
6 changes: 6 additions & 0 deletions AlfredExtraPane/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -62,5 +62,11 @@
<true/>
<key>NSSupportsSuddenTermination</key>
<true/>
<key>SUEnableAutomaticChecks</key>
<true/>
<key>SUFeedURL</key>
<string>https://github.com/mr-pennyworth/alfred-extra-pane/releases/latest/download/appcast.xml</string>
<key>SUPublicEDKey</key>
<string>BAurF5ltFG9az2kGR/+01BftlDBsNg/vm7NGgdP4JNI=</string>
</dict>
</plist>
31 changes: 22 additions & 9 deletions AlfredExtraPane/main.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Alfred
import AppKit
import Foundation

import Sparkle

class AppDelegate: NSObject, NSApplicationDelegate {
let fs = FileManager.default
Expand All @@ -11,16 +11,21 @@ class AppDelegate: NSObject, NSApplicationDelegate {
workflowUID: "*"
)
var statusItem: NSStatusItem?

let updaterController = SPUStandardUpdaterController(
startingUpdater: true,
updaterDelegate: nil,
userDriverDelegate: nil
)

override init() {
super.init()
let confs: [PaneConfig] =
(try? read(contentsOf: configFile())) ?? [defaultConfig]
panes = confs.map { Pane(config: $0) }
}

func applicationDidFinishLaunching(_ notification: Notification) {
setupMenubarExtra()
setupMenubarExtra()
}

func application(_ application: NSApplication, open urls: [URL]) {
Expand Down Expand Up @@ -55,7 +60,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
}
return conf
}

func setupMenubarExtra() {
let appName =
Bundle.main.object(forInfoDictionaryKey: "CFBundleName") as! String
Expand All @@ -70,18 +75,26 @@ class AppDelegate: NSObject, NSApplicationDelegate {
button.image = image
button.toolTip = appName
}

let menu = NSMenu()
menu.addItem(NSMenuItem(
title: "Check for Updates",
action: #selector(checkForUpdates),
keyEquivalent: "u"
))
menu.addItem(NSMenuItem(
title: "Restart " + appName,
action: #selector(restart),
keyEquivalent: "r"
))

statusItem?.menu = menu
}



@objc func checkForUpdates() {
updaterController.checkForUpdates(nil)
}

@objc func restart() {
let task = Process()
task.launchPath = "/usr/bin/open"
Expand Down
57 changes: 57 additions & 0 deletions gen-appcast.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
REPO="https://github.com/mr-pennyworth/alfred-extra-pane"
SPARKLE_RELEASES="https://github.com/sparkle-project/Sparkle/releases/download"
APPCAST_XML="appcast.xml"
vSPARKLE="2.6.4"
SPARKLE_DIST_ZIP="Sparkle-$vSPARKLE.tar.xz"
SPARKLE_DIST_URL="$SPARKLE_RELEASES/$vSPARKLE/$SPARKLE_DIST_ZIP"

app_version="$1"
prev_tag="$2"
signing_key_file="$3"
latest_appcast_url="$REPO/releases/download/$prev_tag/$APPCAST_XML"

# Download the sparkle distribution, extract it, and copy the signer binary
# so that we can sign the AlfredExtraPane.app.zip file.
function download_sparkle_dist() {
if [ ! -d Sparkle ]; then
wget "$SPARKLE_DIST_URL"
mkdir -p Sparkle
tar -xf "$SPARKLE_DIST_ZIP" -C Sparkle
fi
}

function signature() {
./Sparkle/bin/sign_update \
AlfredExtraPane.app.zip -f "$signing_key_file"
}

function new_appcast_item() {
cat <<EOF
<item>
<title>Version ${app_version}</title>
<pubDate>$(date -u +"%a, %d %b %Y %H:%M:%S %z")</pubDate>
<enclosure
url="$REPO/releases/download/${app_version}/AlfredExtraPane.app.zip"
sparkle:version="${app_version}"
sparkle:shortVersionString="${app_version}"
$(signature)
type="application/octet-stream"/>
</item>
EOF
}

# Download the appcast.xml file, then add the new appcast item to it.
# Finally, upload the updated appcast.xml file to the repo.
function update_appcast() {
rm -f $APPCAST_XML
wget "$latest_appcast_url"

head -n6 $APPCAST_XML
new_appcast_item
tail -n+7 $APPCAST_XML
}

download_sparkle_dist
update_appcast > appcast.new.xml
mv appcast.new.xml $APPCAST_XML

0 comments on commit 1096028

Please sign in to comment.