Files
spacedrive/scripts/utils/shared.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

201 lines
5.7 KiB
JavaScript

import { exec as execCb } from 'node:child_process'
import * as fs from 'node:fs/promises'
import * as path from 'node:path'
import { env } from 'node:process'
import { promisify } from 'node:util'
const exec = promisify(execCb)
const signId = env.APPLE_SIGNING_IDENTITY || '-'
/**
* @param {string} origin
* @param {string} target
* @param {boolean} [rename]
*/
async function link(origin, target, rename) {
const parent = path.dirname(target)
await fs.mkdir(parent, { recursive: true, mode: 0o751 })
await (rename ? fs.rename(origin, target) : fs.symlink(path.relative(parent, origin), target))
}
/**
* Move headers and dylibs of external deps to our framework
* @param {string} nativeDeps
*/
export async function setupMacOsFramework(nativeDeps) {
// External deps
const lib = path.join(nativeDeps, 'lib')
const include = path.join(nativeDeps, 'include')
// Framework
const framework = path.join(nativeDeps, 'FFMpeg.framework')
const headers = path.join(framework, 'Headers')
const libraries = path.join(framework, 'Libraries')
const documentation = path.join(framework, 'Resources', 'English.lproj', 'Documentation')
// Move files
await Promise.all([
// Move pdfium license to framework
fs.rename(
path.join(nativeDeps, 'LICENSE.pdfium'),
path.join(documentation, 'LICENSE.pdfium')
),
// Move dylibs to framework
fs.readdir(lib, { recursive: true, withFileTypes: true }).then(file =>
file
.filter(
entry =>
(entry.isFile() || entry.isSymbolicLink()) && entry.name.endsWith('.dylib')
)
.map(entry => {
const file = path.join(entry.path, entry.name)
const newFile = path.resolve(libraries, path.relative(lib, file))
return link(file, newFile, true)
})
),
// Move headers to framework
fs.readdir(include, { recursive: true, withFileTypes: true }).then(file =>
file
.filter(
entry =>
(entry.isFile() || entry.isSymbolicLink()) &&
!entry.name.endsWith('.proto')
)
.map(entry => {
const file = path.join(entry.path, entry.name)
const newFile = path.resolve(headers, path.relative(include, file))
return link(file, newFile, true)
})
),
])
}
/**
* Symlink shared libs paths for Linux
* @param {string} root
* @param {string} nativeDeps
* @returns {Promise<void>}
*/
export async function symlinkSharedLibsLinux(root, nativeDeps) {
// rpath=${ORIGIN}/../lib/spacedrive
const targetLib = path.join(root, 'target', 'lib')
const targetRPath = path.join(targetLib, 'spacedrive')
await fs.unlink(targetRPath).catch(() => {})
await fs.mkdir(targetLib, { recursive: true })
await link(path.join(nativeDeps, 'lib'), targetRPath)
}
/**
* Symlink shared libs paths for macOS
* @param {string} nativeDeps
*/
export async function symlinkSharedLibsMacOS(nativeDeps) {
// External deps
const lib = path.join(nativeDeps, 'lib')
const include = path.join(nativeDeps, 'include')
// Framework
const framework = path.join(nativeDeps, 'FFMpeg.framework')
const headers = path.join(framework, 'Headers')
const libraries = path.join(framework, 'Libraries')
// Link files
await Promise.all([
// Link header files
fs.readdir(headers, { recursive: true, withFileTypes: true }).then(files =>
Promise.all(
files
.filter(entry => entry.isFile() || entry.isSymbolicLink())
.map(entry => {
const file = path.join(entry.path, entry.name)
return link(file, path.resolve(include, path.relative(headers, file)))
})
)
),
// Link dylibs
fs.readdir(libraries, { recursive: true, withFileTypes: true }).then(files =>
Promise.all(
files
.filter(
entry =>
(entry.isFile() || entry.isSymbolicLink()) &&
entry.name.endsWith('.dylib')
)
.map(entry => {
const file = path.join(entry.path, entry.name)
/** @type {Promise<unknown>[]} */
const actions = [
link(file, path.resolve(lib, path.relative(libraries, file))),
]
// Sign dylib (Required for it to work on macOS 13+)
if (entry.isFile())
actions.push(exec(`codesign -s "${signId}" -f "${file}"`))
return actions.length > 1 ? Promise.all(actions) : actions[0]
})
)
),
])
}
/**
* Copy Windows DLLs for tauri build
* @param {string} root
* @param {string} nativeDeps
* @returns {Promise<{files: string[], toClean: string[]}>}
*/
export async function copyWindowsDLLs(root, nativeDeps) {
const tauriSrc = path.join(root, 'apps', 'desktop', 'src-tauri')
const files = await Promise.all(
await fs.readdir(path.join(nativeDeps, 'bin'), { withFileTypes: true }).then(files =>
files
.filter(entry => entry.isFile() && entry.name.endsWith(`.dll`))
.map(async entry => {
await fs.copyFile(
path.join(entry.path, entry.name),
path.join(tauriSrc, entry.name)
)
return entry.name
})
)
)
return { files, toClean: files.map(file => path.join(tauriSrc, file)) }
}
/**
* Symlink shared libs paths for Linux
* @param {string} root
* @param {string} nativeDeps
* @returns {Promise<{files: string[], toClean: string[]}>}
*/
export async function copyLinuxLibs(root, nativeDeps) {
// rpath=${ORIGIN}/../lib/spacedrive
const tauriSrc = path.join(root, 'apps', 'desktop', 'src-tauri')
const files = await fs
.readdir(path.join(nativeDeps, 'lib'), { withFileTypes: true })
.then(files =>
Promise.all(
files
.filter(
entry =>
(entry.isFile() || entry.isSymbolicLink()) &&
(entry.name.endsWith('.so') || entry.name.includes('.so.'))
)
.map(async entry => {
await fs.copyFile(
path.join(entry.path, entry.name),
path.join(tauriSrc, entry.name)
)
return entry.name
})
)
)
return {
files,
toClean: files.map(file => path.join(tauriSrc, file)),
}
}