blackboardsh/electrobun

Updating apps

YoavCodes opened this issue · 1 comments

Goal

  • seamless update experience
  • all you need is a static file host
  • decouple downloading new app code from downloading new bun or webview runtime (when not using native webview) versions
  • support multiple channels (dev, canary, stable)

Two paths:

  1. bun and webview runtimes are stored in a global location
  2. bun and webview runtimes are bundled with your app bundle

Open questions:

  1. when supporting multiple OSes later, with either of these paths be easier or not feasible. lean toward cross-platform consistency where possible.
  2. what manages the update logic (launcher binary, the bun api)? Most likely in bun so we can leverage native ui and notifications
  3. when does auto-downloading and auto-applying of updates happen? app shutdown, app startup, etc.

Build flow

Option 1: Global runtime cache

dev

  • use symlinks in bundle to bun/webview runtimes in node_modules
    • custom webview runtime can be configured in electrobun.config to a local path
  • create app bundle with app code

distribution

  • use symlinks to global cache for bun/webview runtimes
  • package and notarize app
  • upload with versioned filenames
    • app bundle
    • bun runtime
    • webview runtime
    • new update.json

Option 2: Bundled runtimes

dev

  • copy runtimes into app bundle

distribution

  • copy runtimes into app bundle
  • package and notarize app
  • upload with versioned filenames
    • complete app bundle for first time users
    • app code as .zip
    • bun runtime
    • webview runtime
    • new update.json

Update flow

  • check current channel local version.json vs. hosted update.json version
  • if newer then download in background (allow listening to these events)
  • downloads bun, webview runtime, and app resources separately
  • downloads to a global path
  • automatically applies when the app shuts down or starts up
  • checksum of each part we need to update
  • if all are valid then copies app bundle to tmp location, copies parts into tmp app bundle
  • verifies app bundle checksum (it needs to match what was notarized)
  • if valid then replaces itself and relaunches itself
  • local version.json is part of resources so gets updated to whatever channel/version you change to

Files

// version.json -- in the app bundle
{
    "version": "1.0.0",
    "channel": "stable",
    "url": "http://example.com/update.json"
}

// update.json -- hosted somewhere
{
  "baseUrl": "http://example.com/updates/",
  "channels": {
    "stable": {
      "1.0.0": {
        "notes": "This is a stable release",
        "targets": {
          "windows-x64": {
            "bundle": {
              "checksum": "1234567890abcdef",
              "filesize": 102900
            },
            "app": {
              "checksum": "1234567890abcdef",
              "filesize": 102400
            },
            "bun": {
              "checksum": "abcdef1234567890",
              "filesize": 20480
            },
            "webview": {
              "checksum": "fedcba0987654321",
              "filesize": 30720
            }
          },
          "linux-arm64": {
            "bundle": {
              "checksum": "1234567890abcdef",
              "filesize": 102900
            },
            "app": {
              "checksum": "0987654321fedcba",
              "filesize": 51200
            },
            "bun": {
              "checksum": "abcdef1234567890",
              "filesize": 15360
            },
            "webview": {
              "checksum": "1234567890abcdef",
              "filesize": 20480
            }
          }
        }
      }
    },
    "canary": {
      "1.1.0": {
        "notes": "This is a beta release",
        "targets": {
          // Similar structure for canary builds
        }
      }
    },
    "dev": {
      "1.2.0": {
        "notes": "This is a dev release",
        "targets": {
          // Similar structure for dev builds
        }
      }
    }
  }
}

Tasks:

  • rewrite bundle launcher in zig (step toward cross platform)
  • move mac bundle js files into Resources folder
  • update electrobun.config to have version
  • for dev the version number is the git commit sha
  • add command to electrobun cli to build --canary and build --stable
  • add version.json
  • build command should only build for local architecture
  • build --canary and --stable should minify everything and generate arm and intel builds
  • configure objc and zig to build arm or intel
  • generate update.json and all artifacts with deterministic names ready for upload
  • basic file upload and replace for google cloud bucket
  • update logic (in electrobun's bun api, and/or zig launcher) to read local.json, update.json, downloading, verifying, and installing updates)
  • emit events for the update flow

the flow is a bit different but wrapped up the first implementation of updates last week. will write up proper docs soon.