♻️ Split browser updates into a seperate file

This commit is contained in:
trickypr 2022-07-12 15:52:58 +10:00
parent ba2989bfa6
commit 722fcb83eb
5 changed files with 211 additions and 162 deletions

View file

@ -0,0 +1,177 @@
import { existsSync } from 'fs'
import { readFile, stat, writeFile } from 'fs/promises'
import { parse } from 'ini'
import { isAppleSilicon } from 'is-apple-silicon'
import { dirname, join } from 'path'
import { create } from 'xmlbuilder2'
import { bin_name, config } from '../..'
import { DIST_DIR, OBJ_DIR } from '../../constants'
import { log } from '../../log'
import {
dynamicConfig,
ensureEmpty,
generateHash,
ReleaseInfo,
} from '../../utils'
/**
* These are all of the different platforms that aus should deploy to. Note that
* the names have been simplified and they are all only the ones that are
* supported by Pulse Browser. If you need something else, open an issue on gh.
*
* Based off the code from mozrelease:
* https://searchfox.org/mozilla-central/source/python/mozrelease/mozrelease/platforms.py
* https://searchfox.org/mozilla-central/source/taskcluster/gecko_taskgraph/util/partials.py
*/
const ausPlatformsMap = {
linux64: ['Linux_x86_64-gcc3'],
macosIntel: [
'Darwin_x86_64-gcc3-u-i386-x86_64',
'Darwin_x86-gcc3-u-i386-x86_64',
'Darwin_x86-gcc3',
'Darwin_x86_64-gcc3',
],
macosArm: ['Darwin_aarch64-gcc3'],
win64: ['WINNT_x86_64-msvc', 'WINNT_x86_64-msvc-x64'],
}
export async function getPlatformConfig() {
let platformINI = join(OBJ_DIR, 'dist', config.binaryName, 'platform.ini')
if (!existsSync(platformINI))
platformINI = join(OBJ_DIR, 'dist', 'bin', 'platform.ini')
return parse((await readFile(platformINI)).toString())
}
function getReleaseMarName(releaseInfo: ReleaseInfo): string | undefined {
if (isAppleSilicon()) {
log.askForReport()
log.warning('Apple silicon is not yet supported by the distribution script')
return
}
switch (process.platform) {
case 'win32':
return releaseInfo.x86?.windowsMar
case 'darwin':
return releaseInfo.x86?.macosMar
case 'linux':
return releaseInfo.x86?.linuxMar
}
}
function getReleaseMarURL(releaseInfo: ReleaseInfo) {
const releaseMarName = getReleaseMarName(releaseInfo)
let completeMarURL = `https://${config.updateHostname || 'localhost:8000'}/${
releaseMarName || 'output.mar'
}`
// The user is using github to distribute release binaries for this version.
if (releaseInfo.github) {
completeMarURL = `https://github.com/${releaseInfo.github.repo}/releases/download/${releaseInfo.displayVersion}/${releaseMarName}`
log.info(`Using '${completeMarURL}' as the distribution url`)
} else {
log.warning(
`No release information found! Default release location will be "${completeMarURL}"`
)
}
return completeMarURL
}
async function writeUpdateFileToDisk(
target: string,
channel: string,
updateObject: {
updates: {
update: Record<string, any>
}
}
) {
const xmlPath = join(
DIST_DIR,
'update',
'browser',
target,
channel,
'update.xml'
)
const document = create(updateObject)
ensureEmpty(dirname(xmlPath))
await writeFile(xmlPath, document.end({ prettyPrint: true }))
}
function getTargets(): string[] {
if (process.platform == 'win32') {
return ausPlatformsMap.win64
}
if (process.platform == 'linux') {
return ausPlatformsMap.linux64
}
// Everything else will have to be darwin of some kind. So, for future possible
// Apple silicon support, we should chose between the two wisely
// TODO: This is a hack, fix it
if (isAppleSilicon()) {
return ausPlatformsMap.macosArm
}
return ausPlatformsMap.macosIntel
}
export async function generateBrowserUpdateFiles() {
log.info('Creating browser AUS update files')
const brandingKey = dynamicConfig.get('brand') as string
const channel = brandingKey
const brandingDetails = config.brands[brandingKey]
const releaseInfo = brandingDetails.release
const { displayVersion: version } = releaseInfo
const marPath = dynamicConfig.get('marPath')
if (!marPath || marPath == '') {
log.error(
`No mar file has been built! Make sure you ran |${bin_name} package| before this command`
)
return
}
// We need the sha512 hash of the mar file for the update file. AUS will use
// this to ensure that the mar file has not been modified on the distribution
// server
const marHash = generateHash(marPath, 'sha512')
// We need platform information, primarily for the BuildID, but other stuff
// might be helpful later
const platform = await getPlatformConfig()
const completeMarURL = getReleaseMarURL(releaseInfo)
const updateObject = {
updates: {
update: {
// TODO: Correct update type from semvar, store the old version somewhere
'@type': 'minor',
'@displayVersion': version,
'@appVersion': version,
'@platformVersion': config.version.version,
'@buildID': platform.Build.BuildID,
patch: {
// TODO: Partial patches might be nice for download speed
'@type': 'complete',
'@URL': completeMarURL,
'@hashFunction': 'sha512',
'@hashValue': marHash,
'@size': (await stat(marPath)).size,
},
},
},
}
for (const target of getTargets()) {
await writeUpdateFileToDisk(target, channel, updateObject)
}
}