From efeb0d28b7609eaf81b75b2189b1a92e40bcf62a Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Sun, 19 Jan 2025 02:59:22 -0800 Subject: [PATCH 01/12] tab switch fix --- .../void/browser/helperServices/consistentItemService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/void/browser/helperServices/consistentItemService.ts b/src/vs/workbench/contrib/void/browser/helperServices/consistentItemService.ts index 8bde2321..6de0b53b 100644 --- a/src/vs/workbench/contrib/void/browser/helperServices/consistentItemService.ts +++ b/src/vs/workbench/contrib/void/browser/helperServices/consistentItemService.ts @@ -80,7 +80,7 @@ export class ConsistentItemService extends Disposable { } const initializeEditor = (editor: ICodeEditor) => { - if (editor.getModel()?.uri.scheme !== 'file') return + // if (editor.getModel()?.uri.scheme !== 'file') return // THIS BREAKS THINGS addTabSwitchListeners(editor) addDisposeListener(editor) putItemsOnEditor(editor, editor.getModel()?.uri ?? null) From 66e349c72e7abc6435f60d7bf59e239dc0dc31de Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Sun, 19 Jan 2025 06:21:09 -0800 Subject: [PATCH 02/12] fix updates part 1 --- .../electron-main/abstractUpdateService.ts | 36 ++++++++++--------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/src/vs/platform/update/electron-main/abstractUpdateService.ts b/src/vs/platform/update/electron-main/abstractUpdateService.ts index 2d3134d8..d034f395 100644 --- a/src/vs/platform/update/electron-main/abstractUpdateService.ts +++ b/src/vs/platform/update/electron-main/abstractUpdateService.ts @@ -8,6 +8,7 @@ import { CancellationToken } from '../../../base/common/cancellation.js'; import { Emitter, Event } from '../../../base/common/event.js'; import { IConfigurationService } from '../../configuration/common/configuration.js'; import { IEnvironmentMainService } from '../../environment/electron-main/environmentMainService.js'; +// import { IEnvironmentMainService } from '../../environment/electron-main/environmentMainService.js'; import { ILifecycleMainService, LifecycleMainPhase } from '../../lifecycle/electron-main/lifecycleMainService.js'; import { ILogService } from '../../log/common/log.js'; import { IProductService } from '../../product/common/productService.js'; @@ -94,29 +95,30 @@ export abstract class AbstractUpdateService implements IUpdateService { // Void - for now, always update - const updateMode = 'default' //this.configurationService.getValue<'none' | 'manual' | 'start' | 'default'>('update.mode'); + // const updateMode = 'default' //this.configurationService.getValue<'none' | 'manual' | 'start' | 'default'>('update.mode'); - const quality = this.getProductQuality(updateMode); - if (!quality) { - this.setState(State.Disabled(DisablementReason.ManuallyDisabled)); - this.logService.info('update#ctor - updates are disabled by user preference'); - return; - } + // const quality = this.getProductQuality(updateMode); + // if (!quality) { + // console.log('disabling....', updateMode, quality) + // this.setState(State.Disabled(DisablementReason.ManuallyDisabled)); + // this.logService.info('update#ctor - updates are disabled by user preference'); + // return; + // } // const quality = 'stable' - this.url = this.doBuildUpdateFeedUrl(quality); + this.url = this.doBuildUpdateFeedUrl('stable'); if (!this.url) { this.setState(State.Disabled(DisablementReason.InvalidConfiguration)); this.logService.info('update#ctor - updates are disabled as the update URL is badly formed'); return; } - // hidden setting - if (this.configurationService.getValue('_update.prss')) { - const url = new URL(this.url); - url.searchParams.set('prss', 'true'); - this.url = url.toString(); - } + // // hidden setting + // if (this.configurationService.getValue('_update.prss')) { + // const url = new URL(this.url); + // url.searchParams.set('prss', 'true'); + // this.url = url.toString(); + // } this.setState(State.Idle(this.getUpdateType())); @@ -136,9 +138,9 @@ export abstract class AbstractUpdateService implements IUpdateService { // } } - private getProductQuality(updateMode: string): string | undefined { - return updateMode === 'none' ? undefined : this.productService.quality; - } + // private getProductQuality(updateMode: string): string | undefined { + // return updateMode === 'none' ? undefined : this.productService.quality; + // } private async scheduleCheckForUpdates(delay = 60 * 60 * 1000): Promise { await timeout(delay); From 4eff8f8e766c5e969b7b545a72b28c27f3c87b17 Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Sun, 19 Jan 2025 17:23:00 -0800 Subject: [PATCH 03/12] building files --- void-application/.gitignore | 1 + void-application/mac-sign.sh | 164 +++++++++++++++++++++++++++++++++++ void-application/mac.sh | 16 ++++ void-application/windows.sh | 13 +++ 4 files changed, 194 insertions(+) create mode 100644 void-application/.gitignore create mode 100755 void-application/mac-sign.sh create mode 100755 void-application/mac.sh create mode 100755 void-application/windows.sh diff --git a/void-application/.gitignore b/void-application/.gitignore new file mode 100644 index 00000000..967eec8b --- /dev/null +++ b/void-application/.gitignore @@ -0,0 +1 @@ +mac-env.sh diff --git a/void-application/mac-sign.sh b/void-application/mac-sign.sh new file mode 100755 index 00000000..738dc1c1 --- /dev/null +++ b/void-application/mac-sign.sh @@ -0,0 +1,164 @@ +#!/usr/bin/env bash + +set -e # Exit on error + +# Usage: sign.sh {sign|notarize} {arm64|x64} + + + + +echo "-------------------- Setting local variables... --------------------" +ARCH=$2 + + +# Required variables: +# ORIGINAL_DOTAPP_DIR="${HOME}/Desktop/VSCode-darwin-${ARCH}" # location of original (nothing is modified in this dir, just copied away from it) +# WORKING_DIR="${HOME}/Desktop/VoidSign-${ARCH}" # temp dir for all the work here +# P12_FILE="${HOME}/Desktop/sign/cert.p12" +# P12_PASSWORD="..." +# APPLE_ID="..." +# TEAM_ID="..." +# APP_PASSWORD="..." # see https://appleid.apple.com +# CODESIGN_IDENTITY="Developer ID Application: ..." # try `security find-identity -v -p codesigning` + + + +## computed +KEYCHAIN_DIR="${WORKING_DIR}/1_Keychain" +KEYCHAIN="${KEYCHAIN_DIR}/buildagent.keychain" + +SIGN_DIR="${WORKING_DIR}/2_Signed" +SIGNED_DOTAPP_DIR="${SIGN_DIR}/VSCode-darwin-${ARCH}" +SIGNED_DOTAPP="${SIGN_DIR}/VSCode-darwin-${ARCH}/Void.app" + +SIGNED_DMG_DIR="${SIGN_DIR}/VSCode-darwin-${ARCH}" +SIGNED_DMG="${SIGN_DIR}/VSCode-darwin-${ARCH}/Void-Installer-darwin-${ARCH}.dmg" + +echo $KEYCHAIN_DIR + + + + +sign() { + + echo "-------------------- 0. cleanup + copy --------------------" + rm -rf "${WORKING_DIR}" + + mkdir "${WORKING_DIR}" + mkdir "${KEYCHAIN_DIR}" + mkdir "${SIGN_DIR}" + + cp -Rp $ORIGINAL_DOTAPP_DIR $SIGN_DIR + + + echo "-------------------- 1. Make temp keychain --------------------" + # Create a new keychain + security create-keychain -p pwd "${KEYCHAIN}" + security set-keychain-settings -lut 21600 "${KEYCHAIN}" + security unlock-keychain -p pwd "${KEYCHAIN}" + + + # Import your p12 certificate + security import "${P12_FILE}" -k "${KEYCHAIN}" -P "${P12_PASSWORD}" -T /usr/bin/codesign + security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k pwd "${KEYCHAIN}" > /dev/null + + + echo "-------------------- 2a. Sign --------------------" + cd "${HOME}/Desktop/void/build/darwin" + + # used in sign.js + export AGENT_TEMPDIRECTORY=$KEYCHAIN_DIR + export CODESIGN_IDENTITY="${CODESIGN_IDENTITY}" + export VSCODE_ARCH=$ARCH + node sign.js "${SIGN_DIR}" + codesign --verify --verbose=4 "${SIGNED_DOTAPP}" + + echo "-------------------- 2b. Make into dmg --------------------" + npx create-dmg --volname "Void Installer" "${SIGNED_DOTAPP}" "${SIGNED_DMG_DIR}" + # there are two create-dmgs https://github.com/create-dmg/create-dmg https://github.com/sindresorhus/create-dmg the latter one is on npm and works better + GENERATED_DMG=$(ls "${SIGNED_DMG_DIR}"/*.dmg) # figure out the full path of the generated file because create-dmg is stupid + if [[ -z "$GENERATED_DMG" ]]; then + echo "Error: No .dmg file was created." + exit 1 + fi + mv "${GENERATED_DMG}" "${SIGNED_DMG}" # rename + + # We don't even have to codesign - apparently create-dmg does it! codesign --deep --options runtime --sign "${CODESIGN_IDENTITY}" "${SIGNED_DMG}" create + codesign --verify --verbose=4 "${SIGNED_DMG}" + + echo "-------------------- 2c. zip .app --------------------" + + +} + + +# notarize DMG +notarize(){ + + KEYCHAIN_PROFILE_NAME="Void" # this doesnt seem to do anything but is required + + # echo "-------------------- 4. Notarize --------------------" + # echo "Past history:" + # xcrun notarytool history --keychain-profile "${KEYCHAIN_PROFILE_NAME}" --keychain "${KEYCHAIN}" + echo "Void: Setting credentials..." + xcrun notarytool store-credentials "${KEYCHAIN_PROFILE_NAME}" \ + --apple-id "${APPLE_ID}" \ + --team-id "${TEAM_ID}" \ + --password "${APP_PASSWORD}" \ + --keychain "${KEYCHAIN}" + + echo "Void: Submitting..." + xcrun notarytool submit "${SIGNED_DMG}" \ + --keychain-profile "${KEYCHAIN_PROFILE_NAME}" \ + --keychain "${KEYCHAIN}" \ + --wait + + echo "Done! Stapling..." + # finds notarized ticket that was made and staples it to Void.app + xcrun stapler staple "${SIGNED_DMG}" + + # echo "-------------------- 6. Verify --------------------" + # spctl --assess --verbose=4 "${SIGNED_DMG}" + +} + + +updater(){ + echo "Zipping updater here..." + ZIP_NAME="Void-Updater-darwin-${ARCH}.zip" + zip -r -q "${ZIP_NAME}" "${SIGNED_DOTAPP}" + mv "${ZIP_NAME}" "${SIGNED_DOTAPP_DIR}" + + echo "Done!" +} + +USAGE="Usage: $0 {sign|notarize|updater} {arm64|x64}" + +# check to make sure arm64 or x64 is specified +case "$2" in + arm64) + ;; + x64) + ;; + *) + echo $USAGE + exit 1 + ;; +esac + +# Check the first argument +case "$1" in + sign) + sign + ;; + notarize) + notarize + ;; + updater) + updater + ;; + *) + echo $USAGE + exit 1 + ;; +esac diff --git a/void-application/mac.sh b/void-application/mac.sh new file mode 100755 index 00000000..0b888bb7 --- /dev/null +++ b/void-application/mac.sh @@ -0,0 +1,16 @@ +# Do not run this unless you know what you're doing. + +set -e + +./mac-env.sh + + +npm run vscode-darwin-arm64-min +./mac-sign.sh sign arm64 +./mac-sign.sh notarize arm64 +./mac-sign.sh updater arm64 + +npm run vscode-darwin-x64-min +./mac-sign.sh sign x64 +./mac-sign.sh notarize x64 +./mac-sign.sh updater x64 diff --git a/void-application/windows.sh b/void-application/windows.sh new file mode 100755 index 00000000..66d55433 --- /dev/null +++ b/void-application/windows.sh @@ -0,0 +1,13 @@ + + + +npm run vscode-win32-x64-min +npm run gulp vscode-win32-x64-inno-updater +npm run gulp vscode-win32-x64-system-setup +# change icon + +# npm run vscode-darwin-ia32-min +# npm run gulp vscode-win32-ia32-inno-updater +# npm run gulp vscode-win32-ia32-system-setup +# # change icon + From 6ba9d10a4a48fb1531f07cdaa9aeb96ee8a7bbe5 Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Sun, 19 Jan 2025 17:23:23 -0800 Subject: [PATCH 04/12] update --- void-application/mac.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/void-application/mac.sh b/void-application/mac.sh index 0b888bb7..1e94baec 100755 --- a/void-application/mac.sh +++ b/void-application/mac.sh @@ -2,8 +2,6 @@ set -e -./mac-env.sh - npm run vscode-darwin-arm64-min ./mac-sign.sh sign arm64 From e8c0ee631c60efce1d15cb5e1bc242c045288ce9 Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Sun, 19 Jan 2025 17:36:54 -0800 Subject: [PATCH 05/12] fix --- void-application/mac-sign.sh | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/void-application/mac-sign.sh b/void-application/mac-sign.sh index 738dc1c1..c9c4632e 100755 --- a/void-application/mac-sign.sh +++ b/void-application/mac-sign.sh @@ -86,9 +86,6 @@ sign() { # We don't even have to codesign - apparently create-dmg does it! codesign --deep --options runtime --sign "${CODESIGN_IDENTITY}" "${SIGNED_DMG}" create codesign --verify --verbose=4 "${SIGNED_DMG}" - echo "-------------------- 2c. zip .app --------------------" - - } @@ -124,10 +121,10 @@ notarize(){ updater(){ + cd "${SIGNED_DOTAPP_DIR}" echo "Zipping updater here..." - ZIP_NAME="Void-Updater-darwin-${ARCH}.zip" - zip -r -q "${ZIP_NAME}" "${SIGNED_DOTAPP}" - mv "${ZIP_NAME}" "${SIGNED_DOTAPP_DIR}" + VOIDAPP=$(basename $SIGNED_DOTAPP) + zip -r -q "Void-Updater-darwin-${ARCH}.zip" "${VOIDAPP}" echo "Done!" } From 60d22674e2b56caa91044a5eaa8afa1bb5b4f942 Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Sun, 19 Jan 2025 19:24:44 -0800 Subject: [PATCH 06/12] updates --- .../electron-main/abstractUpdateService.ts | 2 +- .../electron-main/updateService.darwin.ts | 2 +- .../electron-main/updateService.win32.ts | 2 +- void-application/mac-sign.sh | 21 +++++++++++++++++++ void-application/mac.sh | 6 ++++-- void-application/windows.sh | 2 +- 6 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/vs/platform/update/electron-main/abstractUpdateService.ts b/src/vs/platform/update/electron-main/abstractUpdateService.ts index d034f395..eeccb05a 100644 --- a/src/vs/platform/update/electron-main/abstractUpdateService.ts +++ b/src/vs/platform/update/electron-main/abstractUpdateService.ts @@ -61,7 +61,7 @@ export abstract class AbstractUpdateService implements IUpdateService { @IEnvironmentMainService private readonly environmentMainService: IEnvironmentMainService, @IRequestService protected requestService: IRequestService, @ILogService protected logService: ILogService, - @IProductService protected readonly productService: IProductService + @IProductService protected readonly productService: IProductService, ) { lifecycleMainService.when(LifecycleMainPhase.AfterWindowOpen) .finally(() => this.initialize()); diff --git a/src/vs/platform/update/electron-main/updateService.darwin.ts b/src/vs/platform/update/electron-main/updateService.darwin.ts index c521b76f..5b00195a 100644 --- a/src/vs/platform/update/electron-main/updateService.darwin.ts +++ b/src/vs/platform/update/electron-main/updateService.darwin.ts @@ -34,7 +34,7 @@ export class DarwinUpdateService extends AbstractUpdateService implements IRelau @IEnvironmentMainService environmentMainService: IEnvironmentMainService, @IRequestService requestService: IRequestService, @ILogService logService: ILogService, - @IProductService productService: IProductService + @IProductService productService: IProductService, ) { super(lifecycleMainService, configurationService, environmentMainService, requestService, logService, productService); diff --git a/src/vs/platform/update/electron-main/updateService.win32.ts b/src/vs/platform/update/electron-main/updateService.win32.ts index c987ecce..0e2396a6 100644 --- a/src/vs/platform/update/electron-main/updateService.win32.ts +++ b/src/vs/platform/update/electron-main/updateService.win32.ts @@ -67,7 +67,7 @@ export class Win32UpdateService extends AbstractUpdateService implements IRelaun @ILogService logService: ILogService, @IFileService private readonly fileService: IFileService, @INativeHostMainService private readonly nativeHostMainService: INativeHostMainService, - @IProductService productService: IProductService + @IProductService productService: IProductService, ) { super(lifecycleMainService, configurationService, environmentMainService, requestService, logService, productService); diff --git a/void-application/mac-sign.sh b/void-application/mac-sign.sh index c9c4632e..838dc9b8 100755 --- a/void-application/mac-sign.sh +++ b/void-application/mac-sign.sh @@ -129,6 +129,24 @@ updater(){ echo "Done!" } + +computehash() { + cd "${SIGNED_DOTAPP_DIR}" + + SHA1=$(shasum -a 1 "${SIGNED_DOTAPP}/Contents/MacOS/Electron" | cut -d' ' -f1) + SHA256=$(shasum -a 256 "${SIGNED_DOTAPP}/Contents/MacOS/Electron" | cut -d' ' -f1) + TIMESTAMP=$(date +%s) + + cat > hash.json << EOF +{ + "sha256hash": "${SHA256}", + "hash": "${SHA1}", + "timestamp": ${TIMESTAMP} +} +EOF +} + + USAGE="Usage: $0 {sign|notarize|updater} {arm64|x64}" # check to make sure arm64 or x64 is specified @@ -154,6 +172,9 @@ case "$1" in updater) updater ;; + computehash) + computehash + ;; *) echo $USAGE exit 1 diff --git a/void-application/mac.sh b/void-application/mac.sh index 1e94baec..0984654c 100755 --- a/void-application/mac.sh +++ b/void-application/mac.sh @@ -3,12 +3,14 @@ set -e -npm run vscode-darwin-arm64-min +npm run gulp vscode-darwin-arm64-min ./mac-sign.sh sign arm64 ./mac-sign.sh notarize arm64 ./mac-sign.sh updater arm64 +./mac-sign.sh computehash arm64 -npm run vscode-darwin-x64-min +npm run gulp vscode-darwin-x64-min ./mac-sign.sh sign x64 ./mac-sign.sh notarize x64 ./mac-sign.sh updater x64 +./mac-sign.sh computehash x64 diff --git a/void-application/windows.sh b/void-application/windows.sh index 66d55433..1f71203f 100755 --- a/void-application/windows.sh +++ b/void-application/windows.sh @@ -1,7 +1,7 @@ -npm run vscode-win32-x64-min +npm run gulp vscode-win32-x64-min npm run gulp vscode-win32-x64-inno-updater npm run gulp vscode-win32-x64-system-setup # change icon From d9be67d17d64bfb1ad31a6e6d10dbdc6931feefa Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Sun, 19 Jan 2025 21:36:48 -0800 Subject: [PATCH 07/12] updates --- .../electron-main/abstractUpdateService.ts | 57 +----- void-application/.gitignore | 1 - void-application/mac-sign.sh | 182 ------------------ void-application/mac.sh | 16 -- void-application/windows.sh | 13 -- 5 files changed, 4 insertions(+), 265 deletions(-) delete mode 100644 void-application/.gitignore delete mode 100755 void-application/mac-sign.sh delete mode 100755 void-application/mac.sh delete mode 100755 void-application/windows.sh diff --git a/src/vs/platform/update/electron-main/abstractUpdateService.ts b/src/vs/platform/update/electron-main/abstractUpdateService.ts index eeccb05a..90fdc074 100644 --- a/src/vs/platform/update/electron-main/abstractUpdateService.ts +++ b/src/vs/platform/update/electron-main/abstractUpdateService.ts @@ -75,37 +75,11 @@ export abstract class AbstractUpdateService implements IUpdateService { protected async initialize(): Promise { if (!this.environmentMainService.isBuilt) { console.log('is NOT built, canceling update service') - this.setState(State.Disabled(DisablementReason.NotBuilt)); - return; // updates are never enabled when running out of sources + // this.setState(State.Disabled(DisablementReason.NotBuilt)); + // return; // updates are never enabled when running out of sources } console.log('is built, continuing with update service') - // Void commented this - // if (this.environmentMainService.disableUpdates) { - // this.setState(State.Disabled(DisablementReason.DisabledByEnvironment)); - // this.logService.info('update#ctor - updates are disabled by the environment'); - // return; - // } - - // if (!this.productService.updateUrl || !this.productService.commit) { - // this.setState(State.Disabled(DisablementReason.MissingConfiguration)); - // this.logService.info('update#ctor - updates are disabled as there is no update URL'); - // return; - // } - - // Void - for now, always update - - // const updateMode = 'default' //this.configurationService.getValue<'none' | 'manual' | 'start' | 'default'>('update.mode'); - - // const quality = this.getProductQuality(updateMode); - // if (!quality) { - // console.log('disabling....', updateMode, quality) - // this.setState(State.Disabled(DisablementReason.ManuallyDisabled)); - // this.logService.info('update#ctor - updates are disabled by user preference'); - // return; - // } - - // const quality = 'stable' this.url = this.doBuildUpdateFeedUrl('stable'); if (!this.url) { this.setState(State.Disabled(DisablementReason.InvalidConfiguration)); @@ -113,35 +87,12 @@ export abstract class AbstractUpdateService implements IUpdateService { return; } - // // hidden setting - // if (this.configurationService.getValue('_update.prss')) { - // const url = new URL(this.url); - // url.searchParams.set('prss', 'true'); - // this.url = url.toString(); - // } - this.setState(State.Idle(this.getUpdateType())); - // if (updateMode === 'manual') { - // this.logService.info('update#ctor - manual checks only; automatic updates are disabled by user preference'); - // return; - // } - - // if (updateMode === 'start') { - // this.logService.info('update#ctor - startup checks only; automatic updates are disabled by user preference'); - - // // Check for updates only once after 30 seconds - // setTimeout(() => this.checkForUpdates(false), 30 * 1000); - // } else { - // Start checking for updates after 30 seconds - this.scheduleCheckForUpdates(30 * 1000).then(undefined, err => this.logService.error(err)); - // } + // start checking for updates after 10 seconds + this.scheduleCheckForUpdates(10 * 1000).then(undefined, err => this.logService.error(err)); } - // private getProductQuality(updateMode: string): string | undefined { - // return updateMode === 'none' ? undefined : this.productService.quality; - // } - private async scheduleCheckForUpdates(delay = 60 * 60 * 1000): Promise { await timeout(delay); await this.checkForUpdates(false); diff --git a/void-application/.gitignore b/void-application/.gitignore deleted file mode 100644 index 967eec8b..00000000 --- a/void-application/.gitignore +++ /dev/null @@ -1 +0,0 @@ -mac-env.sh diff --git a/void-application/mac-sign.sh b/void-application/mac-sign.sh deleted file mode 100755 index 838dc9b8..00000000 --- a/void-application/mac-sign.sh +++ /dev/null @@ -1,182 +0,0 @@ -#!/usr/bin/env bash - -set -e # Exit on error - -# Usage: sign.sh {sign|notarize} {arm64|x64} - - - - -echo "-------------------- Setting local variables... --------------------" -ARCH=$2 - - -# Required variables: -# ORIGINAL_DOTAPP_DIR="${HOME}/Desktop/VSCode-darwin-${ARCH}" # location of original (nothing is modified in this dir, just copied away from it) -# WORKING_DIR="${HOME}/Desktop/VoidSign-${ARCH}" # temp dir for all the work here -# P12_FILE="${HOME}/Desktop/sign/cert.p12" -# P12_PASSWORD="..." -# APPLE_ID="..." -# TEAM_ID="..." -# APP_PASSWORD="..." # see https://appleid.apple.com -# CODESIGN_IDENTITY="Developer ID Application: ..." # try `security find-identity -v -p codesigning` - - - -## computed -KEYCHAIN_DIR="${WORKING_DIR}/1_Keychain" -KEYCHAIN="${KEYCHAIN_DIR}/buildagent.keychain" - -SIGN_DIR="${WORKING_DIR}/2_Signed" -SIGNED_DOTAPP_DIR="${SIGN_DIR}/VSCode-darwin-${ARCH}" -SIGNED_DOTAPP="${SIGN_DIR}/VSCode-darwin-${ARCH}/Void.app" - -SIGNED_DMG_DIR="${SIGN_DIR}/VSCode-darwin-${ARCH}" -SIGNED_DMG="${SIGN_DIR}/VSCode-darwin-${ARCH}/Void-Installer-darwin-${ARCH}.dmg" - -echo $KEYCHAIN_DIR - - - - -sign() { - - echo "-------------------- 0. cleanup + copy --------------------" - rm -rf "${WORKING_DIR}" - - mkdir "${WORKING_DIR}" - mkdir "${KEYCHAIN_DIR}" - mkdir "${SIGN_DIR}" - - cp -Rp $ORIGINAL_DOTAPP_DIR $SIGN_DIR - - - echo "-------------------- 1. Make temp keychain --------------------" - # Create a new keychain - security create-keychain -p pwd "${KEYCHAIN}" - security set-keychain-settings -lut 21600 "${KEYCHAIN}" - security unlock-keychain -p pwd "${KEYCHAIN}" - - - # Import your p12 certificate - security import "${P12_FILE}" -k "${KEYCHAIN}" -P "${P12_PASSWORD}" -T /usr/bin/codesign - security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k pwd "${KEYCHAIN}" > /dev/null - - - echo "-------------------- 2a. Sign --------------------" - cd "${HOME}/Desktop/void/build/darwin" - - # used in sign.js - export AGENT_TEMPDIRECTORY=$KEYCHAIN_DIR - export CODESIGN_IDENTITY="${CODESIGN_IDENTITY}" - export VSCODE_ARCH=$ARCH - node sign.js "${SIGN_DIR}" - codesign --verify --verbose=4 "${SIGNED_DOTAPP}" - - echo "-------------------- 2b. Make into dmg --------------------" - npx create-dmg --volname "Void Installer" "${SIGNED_DOTAPP}" "${SIGNED_DMG_DIR}" - # there are two create-dmgs https://github.com/create-dmg/create-dmg https://github.com/sindresorhus/create-dmg the latter one is on npm and works better - GENERATED_DMG=$(ls "${SIGNED_DMG_DIR}"/*.dmg) # figure out the full path of the generated file because create-dmg is stupid - if [[ -z "$GENERATED_DMG" ]]; then - echo "Error: No .dmg file was created." - exit 1 - fi - mv "${GENERATED_DMG}" "${SIGNED_DMG}" # rename - - # We don't even have to codesign - apparently create-dmg does it! codesign --deep --options runtime --sign "${CODESIGN_IDENTITY}" "${SIGNED_DMG}" create - codesign --verify --verbose=4 "${SIGNED_DMG}" - -} - - -# notarize DMG -notarize(){ - - KEYCHAIN_PROFILE_NAME="Void" # this doesnt seem to do anything but is required - - # echo "-------------------- 4. Notarize --------------------" - # echo "Past history:" - # xcrun notarytool history --keychain-profile "${KEYCHAIN_PROFILE_NAME}" --keychain "${KEYCHAIN}" - echo "Void: Setting credentials..." - xcrun notarytool store-credentials "${KEYCHAIN_PROFILE_NAME}" \ - --apple-id "${APPLE_ID}" \ - --team-id "${TEAM_ID}" \ - --password "${APP_PASSWORD}" \ - --keychain "${KEYCHAIN}" - - echo "Void: Submitting..." - xcrun notarytool submit "${SIGNED_DMG}" \ - --keychain-profile "${KEYCHAIN_PROFILE_NAME}" \ - --keychain "${KEYCHAIN}" \ - --wait - - echo "Done! Stapling..." - # finds notarized ticket that was made and staples it to Void.app - xcrun stapler staple "${SIGNED_DMG}" - - # echo "-------------------- 6. Verify --------------------" - # spctl --assess --verbose=4 "${SIGNED_DMG}" - -} - - -updater(){ - cd "${SIGNED_DOTAPP_DIR}" - echo "Zipping updater here..." - VOIDAPP=$(basename $SIGNED_DOTAPP) - zip -r -q "Void-Updater-darwin-${ARCH}.zip" "${VOIDAPP}" - - echo "Done!" -} - - -computehash() { - cd "${SIGNED_DOTAPP_DIR}" - - SHA1=$(shasum -a 1 "${SIGNED_DOTAPP}/Contents/MacOS/Electron" | cut -d' ' -f1) - SHA256=$(shasum -a 256 "${SIGNED_DOTAPP}/Contents/MacOS/Electron" | cut -d' ' -f1) - TIMESTAMP=$(date +%s) - - cat > hash.json << EOF -{ - "sha256hash": "${SHA256}", - "hash": "${SHA1}", - "timestamp": ${TIMESTAMP} -} -EOF -} - - -USAGE="Usage: $0 {sign|notarize|updater} {arm64|x64}" - -# check to make sure arm64 or x64 is specified -case "$2" in - arm64) - ;; - x64) - ;; - *) - echo $USAGE - exit 1 - ;; -esac - -# Check the first argument -case "$1" in - sign) - sign - ;; - notarize) - notarize - ;; - updater) - updater - ;; - computehash) - computehash - ;; - *) - echo $USAGE - exit 1 - ;; -esac diff --git a/void-application/mac.sh b/void-application/mac.sh deleted file mode 100755 index 0984654c..00000000 --- a/void-application/mac.sh +++ /dev/null @@ -1,16 +0,0 @@ -# Do not run this unless you know what you're doing. - -set -e - - -npm run gulp vscode-darwin-arm64-min -./mac-sign.sh sign arm64 -./mac-sign.sh notarize arm64 -./mac-sign.sh updater arm64 -./mac-sign.sh computehash arm64 - -npm run gulp vscode-darwin-x64-min -./mac-sign.sh sign x64 -./mac-sign.sh notarize x64 -./mac-sign.sh updater x64 -./mac-sign.sh computehash x64 diff --git a/void-application/windows.sh b/void-application/windows.sh deleted file mode 100755 index 1f71203f..00000000 --- a/void-application/windows.sh +++ /dev/null @@ -1,13 +0,0 @@ - - - -npm run gulp vscode-win32-x64-min -npm run gulp vscode-win32-x64-inno-updater -npm run gulp vscode-win32-x64-system-setup -# change icon - -# npm run vscode-darwin-ia32-min -# npm run gulp vscode-win32-ia32-inno-updater -# npm run gulp vscode-win32-ia32-system-setup -# # change icon - From 6e1f8a08b39b9fcc2810356a7e69e65d6e61d13f Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Mon, 20 Jan 2025 00:21:38 -0800 Subject: [PATCH 08/12] void manual updates --- src/vs/code/electron-main/app.ts | 8 ++- .../electron-main/abstractUpdateService.ts | 25 +++++---- .../void/browser/void.contribution.ts | 3 + .../platform/void/common/voidUpdateService.ts | 55 +++++++++++++++++++ .../electron-main/voidUpdateMainService.ts | 48 ++++++++++++++++ .../contrib/void/browser/void.contribution.ts | 3 + .../contrib/void/browser/voidUpdateActions.ts | 42 ++++++++++++++ 7 files changed, 173 insertions(+), 11 deletions(-) create mode 100644 src/vs/platform/void/common/voidUpdateService.ts create mode 100644 src/vs/platform/void/electron-main/voidUpdateMainService.ts create mode 100644 src/vs/workbench/contrib/void/browser/voidUpdateActions.ts diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index 1a027000..f9c50efa 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -124,7 +124,8 @@ import { ExtensionSignatureVerificationService, IExtensionSignatureVerificationS import { LLMMessageChannel } from '../../platform/void/electron-main/llmMessageChannel.js'; import { IMetricsService } from '../../platform/void/common/metricsService.js'; import { MetricsMainService } from '../../platform/void/electron-main/metricsMainService.js'; - +import { VoidMainUpdateService } from '../../platform/void/electron-main/voidUpdateMainService.js'; +import { IVoidUpdateService } from '../../platform/void/common/voidUpdateService.js'; /** * The main VS Code application. There will only ever be one instance, * even if the user starts many instances (e.g. from the command line). @@ -1107,6 +1108,7 @@ export class CodeApplication extends Disposable { // Void main process services (required for services with a channel for comm between browser and electron-main (node)) services.set(IMetricsService, new SyncDescriptor(MetricsMainService, undefined, false)); + services.set(IVoidUpdateService, new SyncDescriptor(VoidMainUpdateService, undefined, false)); // Default Extensions Profile Init services.set(IExtensionsProfileScannerService, new SyncDescriptor(ExtensionsProfileScannerService, undefined, true)); @@ -1245,6 +1247,10 @@ export class CodeApplication extends Disposable { // Void - use loggerChannel as reference const metricsChannel = ProxyChannel.fromService(accessor.get(IMetricsService), disposables); mainProcessElectronServer.registerChannel('void-channel-metrics', metricsChannel); + + const voidUpdatesChannel = ProxyChannel.fromService(accessor.get(IVoidUpdateService), disposables); + mainProcessElectronServer.registerChannel('void-channel-update', voidUpdatesChannel); + const llmMessageChannel = new LLMMessageChannel(accessor.get(IMetricsService)); mainProcessElectronServer.registerChannel('void-channel-llmMessageService', llmMessageChannel); diff --git a/src/vs/platform/update/electron-main/abstractUpdateService.ts b/src/vs/platform/update/electron-main/abstractUpdateService.ts index 90fdc074..92707e34 100644 --- a/src/vs/platform/update/electron-main/abstractUpdateService.ts +++ b/src/vs/platform/update/electron-main/abstractUpdateService.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { timeout } from '../../../base/common/async.js'; +// import { timeout } from '../../../base/common/async.js'; import { CancellationToken } from '../../../base/common/cancellation.js'; import { Emitter, Event } from '../../../base/common/event.js'; import { IConfigurationService } from '../../configuration/common/configuration.js'; @@ -75,8 +75,8 @@ export abstract class AbstractUpdateService implements IUpdateService { protected async initialize(): Promise { if (!this.environmentMainService.isBuilt) { console.log('is NOT built, canceling update service') - // this.setState(State.Disabled(DisablementReason.NotBuilt)); - // return; // updates are never enabled when running out of sources + this.setState(State.Disabled(DisablementReason.NotBuilt)); + return; // updates are never enabled when running out of sources } console.log('is built, continuing with update service') @@ -87,17 +87,22 @@ export abstract class AbstractUpdateService implements IUpdateService { return; } - this.setState(State.Idle(this.getUpdateType())); + this.setState(State.Disabled(DisablementReason.ManuallyDisabled)); + + + // Void - temporarily disabled while we figure out how to do this the right way + + // this.setState(State.Idle(this.getUpdateType())); // start checking for updates after 10 seconds - this.scheduleCheckForUpdates(10 * 1000).then(undefined, err => this.logService.error(err)); + // this.scheduleCheckForUpdates(10 * 1000).then(undefined, err => this.logService.error(err)); } - private async scheduleCheckForUpdates(delay = 60 * 60 * 1000): Promise { - await timeout(delay); - await this.checkForUpdates(false); - return await this.scheduleCheckForUpdates(60 * 60 * 1000); - } + // private async scheduleCheckForUpdates(delay = 60 * 60 * 1000): Promise { + // await timeout(delay); + // await this.checkForUpdates(false); + // return await this.scheduleCheckForUpdates(60 * 60 * 1000); + // } async checkForUpdates(explicit: boolean): Promise { this.logService.trace('update#checkForUpdates, state = ', this.state.type); diff --git a/src/vs/platform/void/browser/void.contribution.ts b/src/vs/platform/void/browser/void.contribution.ts index 1b3cddd2..276d6e72 100644 --- a/src/vs/platform/void/browser/void.contribution.ts +++ b/src/vs/platform/void/browser/void.contribution.ts @@ -16,3 +16,6 @@ import '../common/refreshModelService.js' // metrics import '../common/metricsService.js' + +// updates +import '../common/voidUpdateService.js' diff --git a/src/vs/platform/void/common/voidUpdateService.ts b/src/vs/platform/void/common/voidUpdateService.ts new file mode 100644 index 00000000..5ba02fde --- /dev/null +++ b/src/vs/platform/void/common/voidUpdateService.ts @@ -0,0 +1,55 @@ +/*-------------------------------------------------------------------------------------- + * Copyright 2025 Glass Devtools, Inc. All rights reserved. + * Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information. + *--------------------------------------------------------------------------------------*/ + +import { createDecorator } from '../../instantiation/common/instantiation.js'; +import { ProxyChannel } from '../../../base/parts/ipc/common/ipc.js'; +import { IMainProcessService } from '../../ipc/common/mainProcessService.js'; +import { InstantiationType, registerSingleton } from '../../instantiation/common/extensions.js'; +import { INotificationService, Severity } from '../../notification/common/notification.js'; + + + +export interface IVoidUpdateService { + readonly _serviceBrand: undefined; + check: () => Promise<{ message: string } | null>; +} + + +export const IVoidUpdateService = createDecorator('VoidUpdateService'); + + +// implemented by calling channel +export class VoidUpdateService implements IVoidUpdateService { + + readonly _serviceBrand: undefined; + private readonly voidUpdateService: IVoidUpdateService; + + constructor( + @IMainProcessService mainProcessService: IMainProcessService, // (only usable on client side) + @INotificationService private readonly notifService: INotificationService, + ) { + // creates an IPC proxy to use metricsMainService.ts + this.voidUpdateService = ProxyChannel.toService(mainProcessService.getChannel('void-channel-update')); + } + + + + // anything transmitted over a channel must be async even if it looks like it doesn't have to be + check: IVoidUpdateService['check'] = async () => { + const res = await this.voidUpdateService.check() + const message = res?.message + + this.notifService.notify({ + severity: Severity.Info, + message: message ?? 'This is a very old version of void, please download the latest version! [Void Editor](https://voideditor.com/download-beta)! ', + }) + + return res + } +} + +registerSingleton(IVoidUpdateService, VoidUpdateService, InstantiationType.Eager); + + diff --git a/src/vs/platform/void/electron-main/voidUpdateMainService.ts b/src/vs/platform/void/electron-main/voidUpdateMainService.ts new file mode 100644 index 00000000..b8ca462e --- /dev/null +++ b/src/vs/platform/void/electron-main/voidUpdateMainService.ts @@ -0,0 +1,48 @@ +/*-------------------------------------------------------------------------------------- + * Copyright 2025 Glass Devtools, Inc. All rights reserved. + * Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information. + *--------------------------------------------------------------------------------------*/ + +import { Disposable } from '../../../base/common/lifecycle.js'; +import { IEnvironmentMainService } from '../../environment/electron-main/environmentMainService.js'; + +import { IProductService } from '../../product/common/productService.js'; + +import { IVoidUpdateService } from '../common/voidUpdateService.js'; + + + +export class VoidMainUpdateService extends Disposable implements IVoidUpdateService { + _serviceBrand: undefined; + + constructor( + @IProductService private readonly _productService: IProductService, + @IEnvironmentMainService private readonly _envMainService: IEnvironmentMainService, + ) { + super() + } + + async check() { + const isDevMode = !this._envMainService.isBuilt // found in abstractUpdateService.ts + if (isDevMode) { + console.log('Checking for updates in dev mode') + // return { message: `` } + } + + try { + const res = await fetch(`https://updates.voideditor.dev/api/v0/${this._productService.commit}`) + const resJSON = await res.json() + if (!resJSON) return null + + const { downloadMessage } = resJSON ?? {} + if (!downloadMessage) return null + + const after = downloadMessage + return { message: after } + } + catch (e) { + return null + } + } +} + diff --git a/src/vs/workbench/contrib/void/browser/void.contribution.ts b/src/vs/workbench/contrib/void/browser/void.contribution.ts index 1ab6ebd6..ebb17358 100644 --- a/src/vs/workbench/contrib/void/browser/void.contribution.ts +++ b/src/vs/workbench/contrib/void/browser/void.contribution.ts @@ -26,3 +26,6 @@ import './voidSettingsPane.js' // register css import './media/void.css' + +// update (frontend part, also see platform/) +import './voidUpdateActions.js' diff --git a/src/vs/workbench/contrib/void/browser/voidUpdateActions.ts b/src/vs/workbench/contrib/void/browser/voidUpdateActions.ts new file mode 100644 index 00000000..cd8b9dde --- /dev/null +++ b/src/vs/workbench/contrib/void/browser/voidUpdateActions.ts @@ -0,0 +1,42 @@ +/*-------------------------------------------------------------------------------------- + * Copyright 2025 Glass Devtools, Inc. All rights reserved. + * Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information. + *--------------------------------------------------------------------------------------*/ + +import { Disposable } from '../../../../base/common/lifecycle.js'; +import { ServicesAccessor } from '../../../../editor/browser/editorExtensions.js'; +import { localize2 } from '../../../../nls.js'; +import { Action2, registerAction2 } from '../../../../platform/actions/common/actions.js'; +import { IVoidUpdateService } from '../../../../platform/void/common/voidUpdateService.js'; +import { IWorkbenchContribution, registerWorkbenchContribution2, WorkbenchPhase } from '../../../common/contributions.js'; + + + +// Action +registerAction2(class extends Action2 { + constructor() { + super({ + f1: true, + id: 'void.voidCheckUpdate', + title: localize2('voidCheckUpdate', 'Void: Check for Updates'), + }); + } + async run(accessor: ServicesAccessor): Promise { + + const voidUpdateService = accessor.get(IVoidUpdateService) + voidUpdateService.check() + + } +}) + +// on mount +class VoidUpdateWorkbenchContribution extends Disposable implements IWorkbenchContribution { + static readonly ID = 'workbench.contrib.void.voidUpdate' + constructor( + @IVoidUpdateService private readonly voidUpdateService: IVoidUpdateService + ) { + super() + setTimeout(() => { this.voidUpdateService.check() }, 5 * 1000) + } +} +registerWorkbenchContribution2(VoidUpdateWorkbenchContribution.ID, VoidUpdateWorkbenchContribution, WorkbenchPhase.BlockRestore); From c2fc2577e038514934d21ec9455031cf4c4af5ff Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Mon, 20 Jan 2025 00:31:14 -0800 Subject: [PATCH 09/12] move --- .../platform/void/common/voidUpdateService.ts | 9 ------- .../contrib/void/browser/voidUpdateActions.ts | 26 ++++++++++++++++--- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/src/vs/platform/void/common/voidUpdateService.ts b/src/vs/platform/void/common/voidUpdateService.ts index 5ba02fde..2f4a6264 100644 --- a/src/vs/platform/void/common/voidUpdateService.ts +++ b/src/vs/platform/void/common/voidUpdateService.ts @@ -7,7 +7,6 @@ import { createDecorator } from '../../instantiation/common/instantiation.js'; import { ProxyChannel } from '../../../base/parts/ipc/common/ipc.js'; import { IMainProcessService } from '../../ipc/common/mainProcessService.js'; import { InstantiationType, registerSingleton } from '../../instantiation/common/extensions.js'; -import { INotificationService, Severity } from '../../notification/common/notification.js'; @@ -28,7 +27,6 @@ export class VoidUpdateService implements IVoidUpdateService { constructor( @IMainProcessService mainProcessService: IMainProcessService, // (only usable on client side) - @INotificationService private readonly notifService: INotificationService, ) { // creates an IPC proxy to use metricsMainService.ts this.voidUpdateService = ProxyChannel.toService(mainProcessService.getChannel('void-channel-update')); @@ -39,13 +37,6 @@ export class VoidUpdateService implements IVoidUpdateService { // anything transmitted over a channel must be async even if it looks like it doesn't have to be check: IVoidUpdateService['check'] = async () => { const res = await this.voidUpdateService.check() - const message = res?.message - - this.notifService.notify({ - severity: Severity.Info, - message: message ?? 'This is a very old version of void, please download the latest version! [Void Editor](https://voideditor.com/download-beta)! ', - }) - return res } } diff --git a/src/vs/workbench/contrib/void/browser/voidUpdateActions.ts b/src/vs/workbench/contrib/void/browser/voidUpdateActions.ts index cd8b9dde..d45e4e55 100644 --- a/src/vs/workbench/contrib/void/browser/voidUpdateActions.ts +++ b/src/vs/workbench/contrib/void/browser/voidUpdateActions.ts @@ -4,13 +4,26 @@ *--------------------------------------------------------------------------------------*/ import { Disposable } from '../../../../base/common/lifecycle.js'; +import Severity from '../../../../base/common/severity.js'; import { ServicesAccessor } from '../../../../editor/browser/editorExtensions.js'; import { localize2 } from '../../../../nls.js'; import { Action2, registerAction2 } from '../../../../platform/actions/common/actions.js'; +import { INotificationService } from '../../../../platform/notification/common/notification.js'; import { IVoidUpdateService } from '../../../../platform/void/common/voidUpdateService.js'; import { IWorkbenchContribution, registerWorkbenchContribution2, WorkbenchPhase } from '../../../common/contributions.js'; +const afterGetRes = (res: null | { message: string }, notifService: INotificationService) => { + if (res === null) return + + const message = res?.message ?? 'This is a very old version of void, please download the latest version! [Void Editor](https://voideditor.com/download-beta)! ' + + notifService.notify({ + severity: Severity.Info, + message: message, + }) +} + // Action registerAction2(class extends Action2 { @@ -22,10 +35,11 @@ registerAction2(class extends Action2 { }); } async run(accessor: ServicesAccessor): Promise { - const voidUpdateService = accessor.get(IVoidUpdateService) - voidUpdateService.check() + const notifService = accessor.get(INotificationService) + const res = await voidUpdateService.check() + afterGetRes(res, notifService) } }) @@ -33,10 +47,14 @@ registerAction2(class extends Action2 { class VoidUpdateWorkbenchContribution extends Disposable implements IWorkbenchContribution { static readonly ID = 'workbench.contrib.void.voidUpdate' constructor( - @IVoidUpdateService private readonly voidUpdateService: IVoidUpdateService + @IVoidUpdateService private readonly voidUpdateService: IVoidUpdateService, + @INotificationService private readonly notifService: INotificationService ) { super() - setTimeout(() => { this.voidUpdateService.check() }, 5 * 1000) + setTimeout(async () => { + const res = await this.voidUpdateService.check() + afterGetRes(res, this.notifService) + }, 5 * 1000) } } registerWorkbenchContribution2(VoidUpdateWorkbenchContribution.ID, VoidUpdateWorkbenchContribution, WorkbenchPhase.BlockRestore); From 7519f052386a2d891c488bd2521ff8be9db61d5a Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Mon, 20 Jan 2025 00:51:27 -0800 Subject: [PATCH 10/12] update state --- .../platform/void/common/voidUpdateService.ts | 2 +- .../electron-main/voidUpdateMainService.ts | 11 ++++--- .../contrib/void/browser/voidUpdateActions.ts | 31 ++++++++++++++++--- 3 files changed, 33 insertions(+), 11 deletions(-) diff --git a/src/vs/platform/void/common/voidUpdateService.ts b/src/vs/platform/void/common/voidUpdateService.ts index 2f4a6264..0304073f 100644 --- a/src/vs/platform/void/common/voidUpdateService.ts +++ b/src/vs/platform/void/common/voidUpdateService.ts @@ -12,7 +12,7 @@ import { InstantiationType, registerSingleton } from '../../instantiation/common export interface IVoidUpdateService { readonly _serviceBrand: undefined; - check: () => Promise<{ message: string } | null>; + check: () => Promise<{ hasUpdate: true, message: string } | { hasUpdate: false } | null>; } diff --git a/src/vs/platform/void/electron-main/voidUpdateMainService.ts b/src/vs/platform/void/electron-main/voidUpdateMainService.ts index b8ca462e..97328b62 100644 --- a/src/vs/platform/void/electron-main/voidUpdateMainService.ts +++ b/src/vs/platform/void/electron-main/voidUpdateMainService.ts @@ -30,15 +30,16 @@ export class VoidMainUpdateService extends Disposable implements IVoidUpdateServ } try { - const res = await fetch(`https://updates.voideditor.dev/api/v0/${this._productService.commit}`) + const res = await fetch(`https://updates.voideditor.dev/api/v0/${this._productService.commit ?? '6e1f8a08b39b9fcc2810356a7e69e65d6e61d13f'}`) const resJSON = await res.json() if (!resJSON) return null - const { downloadMessage } = resJSON ?? {} - if (!downloadMessage) return null + const { hasUpdate, downloadMessage } = resJSON ?? {} + if (hasUpdate === undefined) + return null - const after = downloadMessage - return { message: after } + const after = (downloadMessage || '') + '' + return { hasUpdate: !!hasUpdate, message: after } } catch (e) { return null diff --git a/src/vs/workbench/contrib/void/browser/voidUpdateActions.ts b/src/vs/workbench/contrib/void/browser/voidUpdateActions.ts index d45e4e55..ae3e9849 100644 --- a/src/vs/workbench/contrib/void/browser/voidUpdateActions.ts +++ b/src/vs/workbench/contrib/void/browser/voidUpdateActions.ts @@ -13,16 +13,29 @@ import { IVoidUpdateService } from '../../../../platform/void/common/voidUpdateS import { IWorkbenchContribution, registerWorkbenchContribution2, WorkbenchPhase } from '../../../common/contributions.js'; -const afterGetRes = (res: null | { message: string }, notifService: INotificationService) => { - if (res === null) return - const message = res?.message ?? 'This is a very old version of void, please download the latest version! [Void Editor](https://voideditor.com/download-beta)! ' +const notifyYesUpdate = (notifService: INotificationService, msg?: string) => { + const message = msg || 'This is a very old version of void, please download the latest version! [Void Editor](https://voideditor.com/download-beta)!' notifService.notify({ severity: Severity.Info, message: message, }) } +const notifyNoUpdate = (notifService: INotificationService) => { + notifService.notify({ + severity: Severity.Info, + message: 'Void is up-to-date!', + }) +} +const notifyErrChecking = (notifService: INotificationService) => { + const message = `Void Error: There was an error checking for updates. If this persists for a few days, please get in touch or re-download Void [here](https://voideditor.com/download-beta)!` + notifService.notify({ + severity: Severity.Info, + message: message, + }) +} + // Action @@ -39,7 +52,9 @@ registerAction2(class extends Action2 { const notifService = accessor.get(INotificationService) const res = await voidUpdateService.check() - afterGetRes(res, notifService) + if (!res) notifyErrChecking(notifService) + else if (res.hasUpdate) notifyYesUpdate(notifService, res.message) + else if (!res.hasUpdate) notifyNoUpdate(notifService) } }) @@ -51,9 +66,15 @@ class VoidUpdateWorkbenchContribution extends Disposable implements IWorkbenchCo @INotificationService private readonly notifService: INotificationService ) { super() + + // on mount setTimeout(async () => { const res = await this.voidUpdateService.check() - afterGetRes(res, this.notifService) + + if (!res) notifyErrChecking(this.notifService) + else if (res.hasUpdate) notifyYesUpdate(this.notifService, res.message) + else if (!res.hasUpdate) { } // display nothing if up to date + }, 5 * 1000) } } From 8c443ab780cf6dcc7e369f8c9dd78a4deb8282b1 Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Mon, 20 Jan 2025 01:01:33 -0800 Subject: [PATCH 11/12] metrics --- .../electron-main/voidUpdateMainService.ts | 1 + .../contrib/void/browser/voidUpdateActions.ts | 22 ++++++++++++------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/vs/platform/void/electron-main/voidUpdateMainService.ts b/src/vs/platform/void/electron-main/voidUpdateMainService.ts index 97328b62..79def5e9 100644 --- a/src/vs/platform/void/electron-main/voidUpdateMainService.ts +++ b/src/vs/platform/void/electron-main/voidUpdateMainService.ts @@ -32,6 +32,7 @@ export class VoidMainUpdateService extends Disposable implements IVoidUpdateServ try { const res = await fetch(`https://updates.voideditor.dev/api/v0/${this._productService.commit ?? '6e1f8a08b39b9fcc2810356a7e69e65d6e61d13f'}`) const resJSON = await res.json() + if (!resJSON) return null const { hasUpdate, downloadMessage } = resJSON ?? {} diff --git a/src/vs/workbench/contrib/void/browser/voidUpdateActions.ts b/src/vs/workbench/contrib/void/browser/voidUpdateActions.ts index ae3e9849..e58d26ad 100644 --- a/src/vs/workbench/contrib/void/browser/voidUpdateActions.ts +++ b/src/vs/workbench/contrib/void/browser/voidUpdateActions.ts @@ -9,6 +9,7 @@ import { ServicesAccessor } from '../../../../editor/browser/editorExtensions.js import { localize2 } from '../../../../nls.js'; import { Action2, registerAction2 } from '../../../../platform/actions/common/actions.js'; import { INotificationService } from '../../../../platform/notification/common/notification.js'; +import { IMetricsService } from '../../../../platform/void/common/metricsService.js'; import { IVoidUpdateService } from '../../../../platform/void/common/voidUpdateService.js'; import { IWorkbenchContribution, registerWorkbenchContribution2, WorkbenchPhase } from '../../../common/contributions.js'; @@ -29,7 +30,7 @@ const notifyNoUpdate = (notifService: INotificationService) => { }) } const notifyErrChecking = (notifService: INotificationService) => { - const message = `Void Error: There was an error checking for updates. If this persists for a few days, please get in touch or re-download Void [here](https://voideditor.com/download-beta)!` + const message = `Void Error: There was an error checking for updates. If this persists, please get in touch or reinstall Void [here](https://voideditor.com/download-beta)!` notifService.notify({ severity: Severity.Info, message: message, @@ -50,11 +51,12 @@ registerAction2(class extends Action2 { async run(accessor: ServicesAccessor): Promise { const voidUpdateService = accessor.get(IVoidUpdateService) const notifService = accessor.get(INotificationService) + const metricsService = accessor.get(IMetricsService) const res = await voidUpdateService.check() - if (!res) notifyErrChecking(notifService) - else if (res.hasUpdate) notifyYesUpdate(notifService, res.message) - else if (!res.hasUpdate) notifyNoUpdate(notifService) + if (!res) { notifyErrChecking(notifService); metricsService.capture('Void Update: Error', {}) } + else if (res.hasUpdate) { notifyYesUpdate(notifService, res.message); metricsService.capture('Void Update: Yes', {}) } + else if (!res.hasUpdate) { notifyNoUpdate(notifService); metricsService.capture('Void Update: No', {}) } } }) @@ -63,7 +65,8 @@ class VoidUpdateWorkbenchContribution extends Disposable implements IWorkbenchCo static readonly ID = 'workbench.contrib.void.voidUpdate' constructor( @IVoidUpdateService private readonly voidUpdateService: IVoidUpdateService, - @INotificationService private readonly notifService: INotificationService + @INotificationService private readonly notifService: INotificationService, + @IMetricsService private readonly metricsService: IMetricsService, ) { super() @@ -71,9 +74,12 @@ class VoidUpdateWorkbenchContribution extends Disposable implements IWorkbenchCo setTimeout(async () => { const res = await this.voidUpdateService.check() - if (!res) notifyErrChecking(this.notifService) - else if (res.hasUpdate) notifyYesUpdate(this.notifService, res.message) - else if (!res.hasUpdate) { } // display nothing if up to date + const notifService = this.notifService + const metricsService = this.metricsService + + if (!res) { notifyErrChecking(notifService); metricsService.capture('Void Update Startup: Error', {}) } + else if (res.hasUpdate) { notifyYesUpdate(this.notifService, res.message); metricsService.capture('Void Update Startup: Yes', {}) } + else if (!res.hasUpdate) { metricsService.capture('Void Update Startup: No', {}) } // display nothing if up to date }, 5 * 1000) } From 1b4943f39e76924600633712f14678964c6b8358 Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Mon, 20 Jan 2025 01:03:53 -0800 Subject: [PATCH 12/12] devmode --- src/vs/platform/void/electron-main/voidUpdateMainService.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/platform/void/electron-main/voidUpdateMainService.ts b/src/vs/platform/void/electron-main/voidUpdateMainService.ts index 79def5e9..029db5f4 100644 --- a/src/vs/platform/void/electron-main/voidUpdateMainService.ts +++ b/src/vs/platform/void/electron-main/voidUpdateMainService.ts @@ -24,13 +24,13 @@ export class VoidMainUpdateService extends Disposable implements IVoidUpdateServ async check() { const isDevMode = !this._envMainService.isBuilt // found in abstractUpdateService.ts + if (isDevMode) { - console.log('Checking for updates in dev mode') - // return { message: `` } + return { hasUpdate: false } as const } try { - const res = await fetch(`https://updates.voideditor.dev/api/v0/${this._productService.commit ?? '6e1f8a08b39b9fcc2810356a7e69e65d6e61d13f'}`) + const res = await fetch(`https://updates.voideditor.dev/api/v0/${this._productService.commit}`) const resJSON = await res.json() if (!resJSON) return null