Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

feat: add auto-updates#176

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
ethanndickson merged 5 commits intomainfromethan/add-auto-updates
Jun 2, 2025
Merged
Show file tree
Hide file tree
Changes fromall commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions.github/workflows/release.yml
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -108,7 +108,7 @@ jobs:
update-cask:
name: Update homebrew-coder cask
runs-on: ${{ github.repository_owner == 'coder' && 'depot-macos-latest' || 'macos-latest'}}
if: ${{ github.repository_owner == 'coder' &&!inputs.dryrun }}
if: ${{ github.repository_owner == 'coder' &&github.event_name == 'release' }}
needs: build
steps:
- name: Checkout
Expand All@@ -124,7 +124,7 @@ jobs:
- name: Update homebrew-coder
env:
GH_TOKEN: ${{ secrets.CODERCI_GITHUB_TOKEN }}
RELEASE_TAG: ${{ github.event_name == 'release' && github.event.release.tag_name || 'preview' }}
RELEASE_TAG: ${{ github.event.release.tag_name }}
ASSIGNEE: ${{ github.actor }}
run: |
git config --global user.email "ci@coder.com"
Expand Down
4 changes: 4 additions & 0 deletionsCoder-Desktop/Coder-Desktop/Coder_DesktopApp.swift
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,6 +3,7 @@ import NetworkExtension
import os
import SDWebImageSVGCoder
import SDWebImageSwiftUI
import Sparkle
import SwiftUI
import UserNotifications
import VPNLib
Expand All@@ -26,6 +27,7 @@ struct DesktopApp: App {
.environmentObject(appDelegate.vpn)
.environmentObject(appDelegate.state)
.environmentObject(appDelegate.helper)
.environmentObject(appDelegate.autoUpdater)
}
.windowResizability(.contentSize)
Window("Coder File Sync", id: Windows.fileSync.rawValue) {
Expand All@@ -47,11 +49,13 @@ class AppDelegate: NSObject, NSApplicationDelegate {
let urlHandler: URLHandler
let notifDelegate: NotifDelegate
let helper: HelperService
let autoUpdater: UpdaterService

override init() {
notifDelegate = NotifDelegate()
vpn = CoderVPNService()
helper = HelperService()
autoUpdater = UpdaterService()
let state = AppState(onChange: vpn.configureTunnelProviderProtocol)
vpn.onStart = {
// We don't need this to have finished before the VPN actually starts
Expand Down
2 changes: 2 additions & 0 deletionsCoder-Desktop/Coder-Desktop/Info.plist
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -35,5 +35,7 @@
<string>Ae2oQLTcx89/a73XrpOt+IVvqdo+fMTjo3UKEm77VdA=</string>
<key>CommitHash</key>
<string>$(GIT_COMMIT_HASH)</string>
<key>SUFeedURL</key>
<string>https://releases.coder.com/coder-desktop/mac/appcast.xml</string>
</dict>
</plist>
87 changes: 87 additions & 0 deletionsCoder-Desktop/Coder-Desktop/UpdaterService.swift
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
import Sparkle
import SwiftUI

final class UpdaterService: NSObject, ObservableObject {
private lazy var inner: SPUStandardUpdaterController = .init(
startingUpdater: true,
updaterDelegate: self,
userDriverDelegate: self
)
private var updater: SPUUpdater!
@Published var canCheckForUpdates = true

@Published var autoCheckForUpdates: Bool! {
didSet {
if let autoCheckForUpdates, autoCheckForUpdates != oldValue {
updater.automaticallyChecksForUpdates = autoCheckForUpdates
}
}
}

@Published var updateChannel: UpdateChannel {
didSet {
UserDefaults.standard.set(updateChannel.rawValue, forKey: Self.updateChannelKey)
}
}

static let updateChannelKey = "updateChannel"

override init() {
updateChannel = UserDefaults.standard.string(forKey: Self.updateChannelKey)
.flatMap { UpdateChannel(rawValue: $0) } ?? .stable
super.init()
updater = inner.updater
autoCheckForUpdates = updater.automaticallyChecksForUpdates
updater.publisher(for: \.canCheckForUpdates).assign(to: &$canCheckForUpdates)
}

func checkForUpdates() {
guard canCheckForUpdates else { return }
updater.checkForUpdates()
}
}

enum UpdateChannel: String, CaseIterable, Identifiable {
case stable
case preview

var name: String {
switch self {
case .stable:
"Stable"
case .preview:
"Preview"
}
}

var id: String { rawValue }
}

extension UpdaterService: SPUUpdaterDelegate {
func allowedChannels(for _: SPUUpdater) -> Set<String> {
// There's currently no point in subscribing to both channels, as
// preview >= stable
[updateChannel.rawValue]
}
}

extension UpdaterService: SUVersionDisplay {
func formatUpdateVersion(
fromUpdate update: SUAppcastItem,
andBundleDisplayVersion inOutBundleDisplayVersion: AutoreleasingUnsafeMutablePointer<NSString>,
withBundleVersion bundleVersion: String
) -> String {
// Replace CFBundleShortVersionString with CFBundleVersion, as the
// latter shows build numbers.
inOutBundleDisplayVersion.pointee = bundleVersion as NSString
// This is already CFBundleVersion, as that's the only version in the
// appcast.
return update.displayVersionString
}
}

extension UpdaterService: SPUStandardUserDriverDelegate {
func standardUserDriverRequestsVersionDisplayer() -> (any SUVersionDisplay)? {
self
}
}
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -174,7 +174,7 @@ class SystemExtensionDelegate<AsyncDelegate: SystemExtensionAsyncRecorder>:
actionForReplacingExtension existing: OSSystemExtensionProperties,
withExtension extension: OSSystemExtensionProperties
) -> OSSystemExtensionRequest.ReplacementAction {
logger.info("Replacing \(request.identifier)v\(existing.bundleVersion) withv\(`extension`.bundleVersion)")
logger.info("Replacing \(request.identifier) \(existing.bundleVersion) with \(`extension`.bundleVersion)")
// This is counterintuitive, but this function is only called if the
// versions are the same in a dev environment.
// In a release build, this only gets called when the version string is
Expand Down
19 changes: 15 additions & 4 deletionsCoder-Desktop/Coder-Desktop/Views/Settings/GeneralTab.swift
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,6 +3,7 @@ import SwiftUI

struct GeneralTab: View {
@EnvironmentObject var state: AppState
@EnvironmentObject var updater: UpdaterService
var body: some View {
Form {
Section {
Expand All@@ -18,10 +19,20 @@ struct GeneralTab: View {
Text("Start Coder Connect on launch")
}
}
Section {
Toggle(isOn: $updater.autoCheckForUpdates) {
Text("Automatically check for updates")
}
Picker("Update channel", selection: $updater.updateChannel) {
ForEach(UpdateChannel.allCases) { channel in
Text(channel.name).tag(channel)
}
}
HStack {
Spacer()
Button("Check for updates") { updater.checkForUpdates() }.disabled(!updater.canCheckForUpdates)
}
}
}.formStyle(.grouped)
}
}

#Preview {
GeneralTab()
}
4 changes: 2 additions & 2 deletionsCoder-Desktop/project.yml
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -11,8 +11,8 @@ options:

settings:
base:
MARKETING_VERSION: ${MARKETING_VERSION} # Setsthe version number.
CURRENT_PROJECT_VERSION: ${CURRENT_PROJECT_VERSION} #Sets the build number.
MARKETING_VERSION: ${MARKETING_VERSION} # SetsCFBundleShortVersionString
CURRENT_PROJECT_VERSION: ${CURRENT_PROJECT_VERSION} #CFBundleVersion
GIT_COMMIT_HASH: ${GIT_COMMIT_HASH}

ALWAYS_SEARCH_USER_PATHS: NO
Expand Down
46 changes: 15 additions & 31 deletionsscripts/update-cask.sh
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,12 +4,12 @@ set -euo pipefail
usage() {
echo "Usage: $0 [--version <version>] [--assignee <github handle>]"
echo " --version <version> Set the VERSION variable to fetch and generate the cask file for"
echo " --assignee <github handle> Set theASSIGNE variable to assign the PR to (optional)"
echo " --assignee <github handle> Set theASSIGNEE variable to assign the PR to (optional)"
echo " -h, --help Display this help message"
}

VERSION=""
ASSIGNE=""
ASSIGNEE=""

# Parse command line arguments
while [[ "$#" -gt 0 ]]; do
Expand All@@ -19,7 +19,7 @@ while [[ "$#" -gt 0 ]]; do
shift 2
;;
--assignee)
ASSIGNE="$2"
ASSIGNEE="$2"
shift 2
;;
-h | --help)
Expand All@@ -39,7 +39,7 @@ done
echo "Error: VERSION cannot be empty"
exit 1
}
[[ "$VERSION" =~ ^v|| "$VERSION" == "preview"]] || {
[[ "$VERSION" =~ ^v ]] || {
echo "Error: VERSION must start with a 'v'"
exit 1
}
Expand All@@ -54,55 +54,39 @@ gh release download "$VERSION" \

HASH=$(shasum -a 256 "$GH_RELEASE_FOLDER"/Coder-Desktop.pkg | awk '{print $1}' | tr -d '\n')

IS_PREVIEW=false
if [[ "$VERSION" == "preview" ]]; then
IS_PREVIEW=true
VERSION=$(make 'print-CURRENT_PROJECT_VERSION' | sed 's/CURRENT_PROJECT_VERSION=//g')
fi

# Check out the homebrew tap repo
TAP_CHECHOUT_FOLDER=$(mktemp -d)
TAP_CHECKOUT_FOLDER=$(mktemp -d)

gh repo clone "coder/homebrew-coder" "$TAP_CHECHOUT_FOLDER"
gh repo clone "coder/homebrew-coder" "$TAP_CHECKOUT_FOLDER"

cd "$TAP_CHECHOUT_FOLDER"
cd "$TAP_CHECKOUT_FOLDER"

BREW_BRANCH="auto-release/desktop-$VERSION"

# Check if a PR already exists.
# Continue on a main branch release, as the sha256 will change.
pr_count="$(gh pr list --search "head:$BREW_BRANCH" --json id,closed | jq -r ".[] | select(.closed == false) | .id" | wc -l)"
if [[ "$pr_count" -gt 0&& "$IS_PREVIEW" == false]]; then
if [[ "$pr_count" -gt 0 ]]; then
echo "Bailing out as PR already exists" 2>&1
exit 0
fi

git checkout -b "$BREW_BRANCH"

# If this is a main branch build, append a preview suffix to the cask.
SUFFIX=""
CONFLICTS_WITH="coder-desktop-preview"
TAG=$VERSION
if [[ "$IS_PREVIEW" == true ]]; then
SUFFIX="-preview"
CONFLICTS_WITH="coder-desktop"
TAG="preview"
fi

mkdir -p "$TAP_CHECHOUT_FOLDER"/Casks
mkdir -p "$TAP_CHECKOUT_FOLDER"/Casks

# Overwrite the cask file
cat >"$TAP_CHECHOUT_FOLDER"/Casks/coder-desktop${SUFFIX}.rb <<EOF
cask "coder-desktop${SUFFIX}" do
cat >"$TAP_CHECKOUT_FOLDER"/Casks/coder-desktop.rb <<EOF
cask "coder-desktop" do
version "${VERSION#v}"
sha256$([ "$IS_PREVIEW" = true ] && echo ":no_check" || echo "\"${HASH}\"")
sha256"${HASH}"

url "https://github.com/coder/coder-desktop-macos/releases/download/$([ "$IS_PREVIEW" = true ] && echo "${TAG}" || echo "v#{version}")/Coder-Desktop.pkg"
url "https://github.com/coder/coder-desktop-macos/releases/download/v#{version}/Coder-Desktop.pkg"
name "Coder Desktop"
desc "Native desktop client for Coder"
homepage "https://github.com/coder/coder-desktop-macos"
auto_updates true

conflicts_with cask: "coder/coder/${CONFLICTS_WITH}"
depends_on macos: ">= :sonoma"

pkg "Coder-Desktop.pkg"
Expand DownExpand Up@@ -132,5 +116,5 @@ if [[ "$pr_count" -eq 0 ]]; then
--base master --head "$BREW_BRANCH" \
--title "Coder Desktop $VERSION" \
--body "This automatic PR was triggered by the release of Coder Desktop $VERSION" \
${ASSIGNE:+ --assignee "$ASSIGNE" --reviewer "$ASSIGNE"}
${ASSIGNEE:+ --assignee "$ASSIGNEE" --reviewer "$ASSIGNEE"}
fi
Loading

[8]ページ先頭

©2009-2025 Movatter.jp