Repository: electron-userland/electron-builder
File: packages/electron-updater/src/AppUpdater.ts (TypeScript)

Code before:
  private async isUpdateAvailable(updateInfo: UpdateInfo): Promise<boolean> {
    const latestVersion = parseVersion(updateInfo.version)
    if (latestVersion == null) {
      throw newError(
        `This file could not be downloaded, or the latest version (from update server) does not have a valid semver version: "${updateInfo.version}"`,
        "ERR_UPDATER_INVALID_VERSION"
      )
    }

    const currentVersion = this.currentVersion
    if (isVersionsEqual(latestVersion, currentVersion)) {
      return false
    }

    const minimumSystemVersion = updateInfo?.minimumSystemVersion
    if (minimumSystemVersion) {
      const currentOSVersion = release()
      if (currentOSVersion && isVersionLessThan(currentOSVersion, minimumSystemVersion)) {
        this._logger.info(`Current OS version ${currentOSVersion} is less than the minimum OS version required ${minimumSystemVersion} for version ${latestVersion}`)
        return false
      }
    }

    const isStagingMatch = await this.isStagingMatch(updateInfo)
    if (!isStagingMatch) {
      return false
    }

    // https://github.com/electron-userland/electron-builder/pull/3111#issuecomment-405033227
    // https://github.com/electron-userland/electron-builder/pull/3111#issuecomment-405030797
    const isLatestVersionNewer = isVersionGreaterThan(latestVersion, currentVersion)
    const isLatestVersionOlder = isVersionLessThan(latestVersion, currentVersion)

    if (isLatestVersionNewer) {
      return true
    }
    return this.allowDowngrade && isLatestVersionOlder
  }

  protected async getUpdateInfoAndProvider(): Promise<UpdateInfoAndProvider> {
    await this.app.whenReady()

    if (this.clientPromise == null) {
      this.clientPromise = this.configOnDisk.value.then(it => createClient(it, this, this.createProviderRuntimeOptions()))
    }

    const client = await this.clientPromise
    const stagingUserId = await this.stagingUserIdPromise.value
    client.setRequestHeaders(this.computeFinalHeaders({ "x-user-staging-id": stagingUserId }))
    return {
      info: await client.getLatestVersion(),

Review comment (suggestion):
I think this may need a try-catch in case an invalid `minimumSystemVersion` is provided

```
const minimumSystemVersion = updateInfo?.minimumSystemVersion
if (minimumSystemVersion) {
  try {
    const currentOSVersion = release()
    if (currentOSVersion && isVersionLessThan(currentOSVersion, minimumSystemVersion)) {
      this._logger.info(`Current OS version ${currentOSVersion} is less than the minimum OS version required ${minimumSystemVersion} for version ${latestVersion}`)
      return false
    }
  } catch (e: any) {
    // log and ignore
    this._logger.warn(`Unable to compare current OS version ${currentOSVersion} to minimum app version ${minimumSystemVersion}. ${ e.message })
  }
}
```

Code after:
  private async isUpdateAvailable(updateInfo: UpdateInfo): Promise<boolean> {
    const latestVersion = parseVersion(updateInfo.version)
    if (latestVersion == null) {
      throw newError(
        `This file could not be downloaded, or the latest version (from update server) does not have a valid semver version: "${updateInfo.version}"`,
        "ERR_UPDATER_INVALID_VERSION"
      )
    }

    const currentVersion = this.currentVersion
    if (isVersionsEqual(latestVersion, currentVersion)) {
      return false
    }

    const minimumSystemVersion = updateInfo?.minimumSystemVersion
    const currentOSVersion = release()
    if (minimumSystemVersion) {
      try {
        if (isVersionLessThan(currentOSVersion, minimumSystemVersion)) {
          this._logger.info(`Current OS version ${currentOSVersion} is less than the minimum OS version required ${minimumSystemVersion} for version ${currentOSVersion}`)
          return false
        }
      } catch (e: any) {
        this._logger.warn(`Failed to compare current OS version(${currentOSVersion}) with minimum OS version(${minimumSystemVersion}): ${(e.message || e).toString()}`)
      }
    }

    const isStagingMatch = await this.isStagingMatch(updateInfo)
    if (!isStagingMatch) {
      return false
    }

    // https://github.com/electron-userland/electron-builder/pull/3111#issuecomment-405033227
    // https://github.com/electron-userland/electron-builder/pull/3111#issuecomment-405030797
    const isLatestVersionNewer = isVersionGreaterThan(latestVersion, currentVersion)
    const isLatestVersionOlder = isVersionLessThan(latestVersion, currentVersion)

    if (isLatestVersionNewer) {
      return true
    }
    return this.allowDowngrade && isLatestVersionOlder
  }

  protected async getUpdateInfoAndProvider(): Promise<UpdateInfoAndProvider> {
    await this.app.whenReady()

    if (this.clientPromise == null) {
      this.clientPromise = this.configOnDisk.value.then(it => createClient(it, this, this.createProviderRuntimeOptions()))
    }

    const client = await this.clientPromise