spacedrive/scripts/utils/patchTauri.mjs
Brendan Allan 49cc098f32
[ENG-927, ENG-735, ENG-766] Fix Updater & Tauri 1.5 (#1361)
* custom updater with toasts

* new state management + updated router route

* tauri-specific update route

* ref

* update in prod only

* change 'Install' to 'Update'

* fix tsconfig

* desktop tauri

* remove tauri patch

* tauri 1.5

* tauri 1.5

* use tauri script

* native-deps

* Rework preprep and tauri script to better support tauri 1.5

* Update to tauri 1.5.1
 - Update workspace and apps/desktop dependencies
 - Fix mustache import, @types/mustache is not compatible with ES imports
 - Replace arm64 with aarch64 in machineID, they should be treated the same and this simplyfies the code

* Fix tauri updater not building due to missing key
 - Fix dmg background not being found
 - Generate an adhoc key for tauri updater with it is enabled and the user is doing a prod build

* Fix ctrl+c/ctrl+v typo

* Normalie @tanstack/react-query version through workspace
 - Use undici in scripts instead of global fetch
 - Fix typecheck

* Fix linux prod and dev builds
 - Improve error handling in tauri.mjs

* Normalize dev deps in workspace
 - Improve linux shared libs setup

* Fix CI and server docker

* Fix windows
 - Remove superfluous envvar

* Attempt to fix server, mobile, deb and release updater

* Attempt to fix deb and mobile again
 - Fix type on deb dependency
 - Enable release deb for aarch64-unknown-linux-gnu

* Github doesn't have arm runners
 - Fix typo in server Dockerfile

* Publish deb and updater artifacts

* remove version from asset name

* update commands

* log release

* Some logs on updater errors

* show updater errors on frontend

* fix desktop ui caching

---------

Co-authored-by: Vítor Vasconcellos <vasconcellos.dev@gmail.com>
Co-authored-by: Ericson Fogo Soares <ericson.ds999@gmail.com>
2023-10-10 07:30:56 +00:00

143 lines
4.1 KiB
JavaScript

import { exec as _exec } from 'node:child_process'
import * as fs from 'node:fs/promises'
import * as os from 'node:os'
import * as path from 'node:path'
import { env } from 'node:process'
import { promisify } from 'node:util'
import * as semver from 'semver'
import { copyLinuxLibs, copyWindowsDLLs } from './shared.mjs'
const exec = promisify(_exec)
const __debug = env.NODE_ENV === 'debug'
/**
* @param {string} nativeDeps
* @returns {Promise<string?>}
*/
export async function tauriUpdaterKey(nativeDeps) {
if (env.TAURI_PRIVATE_KEY) return null
// pnpm exec tauri signer generate -w
const privateKeyPath = path.join(nativeDeps, 'tauri.key')
const publicKeyPath = path.join(nativeDeps, 'tauri.key.pub')
const readKeys = () =>
Promise.all([
fs.readFile(publicKeyPath, { encoding: 'utf-8' }),
fs.readFile(privateKeyPath, { encoding: 'utf-8' }),
])
let privateKey, publicKey
try {
;[publicKey, privateKey] = await readKeys()
if (!(publicKey && privateKey)) throw new Error('Empty keys')
} catch (err) {
if (__debug) {
console.warn('Failed to read tauri updater keys')
console.error(err)
}
const quote = os.type() === 'Windows_NT' ? '"' : "'"
await exec(`pnpm exec tauri signer generate --ci -w ${quote}${privateKeyPath}${quote}`)
;[publicKey, privateKey] = await readKeys()
if (!(publicKey && privateKey)) throw new Error('Empty keys')
}
env.TAURI_PRIVATE_KEY = privateKey
return publicKey
}
/**
* @param {string} root
* @param {string} nativeDeps
* @param {string[]} args
* @returns {Promise<string[]>}
*/
export async function patchTauri(root, nativeDeps, args) {
if (args.findIndex(e => e === '-c' || e === '--config') !== -1) {
throw new Error('Custom tauri build config is not supported.')
}
// Location for desktop app tauri code
const tauriRoot = path.join(root, 'apps', 'desktop', 'src-tauri')
const osType = os.type()
const resources =
osType === 'Linux'
? await copyLinuxLibs(root, nativeDeps)
: osType === 'Windows_NT'
? await copyWindowsDLLs(root, nativeDeps)
: { files: [], toClean: [] }
const tauriPatch = {
tauri: {
bundle: {
macOS: {
minimumSystemVersion: '',
},
resources: resources.files,
},
updater: /** @type {{ pubkey?: string }} */ ({}),
},
}
const tauriConfig = await fs
.readFile(path.join(tauriRoot, 'tauri.conf.json'), 'utf-8')
.then(JSON.parse)
if (args[0] === 'build') {
if (tauriConfig?.tauri?.updater?.active) {
const pubKey = await tauriUpdaterKey(nativeDeps)
if (pubKey != null) tauriPatch.tauri.updater.pubkey = pubKey
}
}
if (osType === 'Darwin') {
// ARM64 support was added in macOS 11, but we need at least 11.2 due to our ffmpeg build
const macOSArm64MinimumVersion = '11.2'
let macOSMinimumVersion = tauriConfig?.tauri?.bundle?.macOS?.minimumSystemVersion
const targets = args
.filter((_, index, args) => {
if (index === 0) return false
const previous = args[index - 1]
return previous === '-t' || previous === '--target'
})
.flatMap(target => target.split(','))
if (
(targets.includes('aarch64-apple-darwin') ||
(targets.length === 0 && process.arch === 'arm64')) &&
(macOSMinimumVersion == null ||
semver.lt(
/** @type {import('semver').SemVer} */ (semver.coerce(macOSMinimumVersion)),
/** @type {import('semver').SemVer} */ (
semver.coerce(macOSArm64MinimumVersion)
)
))
) {
macOSMinimumVersion = macOSArm64MinimumVersion
console.log(
`aarch64-apple-darwin target detected, setting minimum system version to ${macOSMinimumVersion}`
)
}
if (macOSMinimumVersion) {
env.MACOSX_DEPLOYMENT_TARGET = macOSMinimumVersion
tauriPatch.tauri.bundle.macOS.minimumSystemVersion = macOSMinimumVersion
} else {
throw new Error('No minimum macOS version detected, please review tauri.conf.json')
}
}
const tauriPatchConf = path.join(tauriRoot, 'tauri.conf.patch.json')
await fs.writeFile(tauriPatchConf, JSON.stringify(tauriPatch, null, 2))
// Modify args to load patched tauri config
args.splice(1, 0, '-c', tauriPatchConf)
// Files to be removed
return [tauriPatchConf, ...resources.toClean]
}