M1 Support

This commit is contained in:
Fedor Indutny 2021-12-03 23:49:15 +01:00 committed by GitHub
parent dccd3fbf73
commit 874a019227
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 397 additions and 316 deletions

View file

@ -27,7 +27,7 @@ async function go() {
return;
}
const appPath = await findDMG();
const appPaths = await findDMGs();
const appBundleId = packageJson.build.appId;
if (!appBundleId) {
throw new Error(
@ -50,32 +50,41 @@ async function go() {
}
console.log('Notarizing with...');
console.log(` file: ${appPath}`);
console.log(` files: ${appPaths.join(', ')}`);
console.log(` primaryBundleId: ${appBundleId}`);
console.log(` username: ${appleId}`);
await notarize({
appBundleId,
appPath,
appleId,
appleIdPassword,
});
await Promise.all(
appPaths.map(async appPath => {
return notarize({
appBundleId,
appPath,
appleId,
appleIdPassword,
});
})
);
}
const IS_DMG = /\.dmg$/;
async function findDMG(): Promise<string> {
async function findDMGs(): Promise<Array<string>> {
const releaseDir = resolve('release');
const files: Array<string> = await readdir(releaseDir);
const max = files.length;
const results = new Array<string>();
for (let i = 0; i < max; i += 1) {
const file = files[i];
const fullPath = join(releaseDir, file);
if (IS_DMG.test(file)) {
return fullPath;
results.push(fullPath);
}
}
throw new Error("No suitable file found in 'release' folder!");
if (results.length === 0) {
throw new Error("No suitable files found in 'release' folder!");
}
return results;
}

View file

@ -22,61 +22,65 @@ export function zipMacOSRelease(): void {
'No zip file found. Maybe the release did not complete properly?'
);
}
if (files.length > 1) {
if (files.length !== 2) {
throw new Error(
'More than one zip file found, release directory was not cleared.'
'Multiple versions of zip files found, release directory was not cleared.'
);
}
const zipFile = files[0];
const zipPath = path.join('release', zipFile);
console.log('Removing current zip file');
rimraf.sync(zipPath);
for (const zipFile of files) {
const zipPath = path.join('release', zipFile);
const appName = `${packageJSON.productName}.app`;
const appPath = path.join('release', 'mac', appName);
console.log('Removing current zip file', zipFile);
rimraf.sync(zipPath);
const tmpPath = path.join('release', 'tmp');
const appDir = path.dirname(appPath);
const tmpZip = path.join(appDir, zipFile);
console.log('Creating temporary zip file at', tmpZip);
try {
execSync(`cd ${appDir} && zip -ro ${zipFile} "${appName}"`);
console.log(
'Unzipping to remove duplicate electron references from',
tmpZip
const postfix = zipFile.includes('arm64') ? '-arm64' : '';
const appName = `${packageJSON.productName}.app`;
const appPath = path.join('release', `mac${postfix}`, appName);
const tmpPath = path.join('release', `tmp${postfix}`);
const appDir = path.dirname(appPath);
const tmpZip = path.join(appDir, zipFile);
console.log('Creating temporary zip file at', tmpZip);
try {
execSync(`cd ${appDir} && zip -ro ${zipFile} "${appName}"`);
console.log(
'Unzipping to remove duplicate electron references from',
tmpZip
);
execSync(`unzip ${tmpZip} -d ${tmpPath}`);
} catch (err) {
console.log('stdout:', String(err.stdout));
console.log('stderr:', String(err.stderr));
throw err;
}
console.log('Removing temporary zip file');
rimraf.sync(tmpZip);
const electronFrameworkPath = path.join(
tmpPath,
appName,
'Contents',
'Frameworks',
'Electron Framework.framework',
'Versions'
);
execSync(`unzip ${tmpZip} -d ${tmpPath}`);
} catch (err) {
console.log('stdout:', String(err.stdout));
console.log('stderr:', String(err.stderr));
throw err;
}
console.log('Removing temporary zip file');
rimraf.sync(tmpZip);
console.log('Removing duplicate electron framework', electronFrameworkPath);
rimraf.sync(electronFrameworkPath);
const electronFrameworkPath = path.join(
tmpPath,
appName,
'Contents',
'Frameworks',
'Electron Framework.framework',
'Versions'
);
console.log('Removing duplicate electron framework', electronFrameworkPath);
rimraf.sync(electronFrameworkPath);
try {
console.log('Creating final zip');
execSync(`cd ${tmpPath} && zip -ro ${zipFile} "${appName}"`);
} catch (err) {
console.log('stdout:', String(err.stdout));
console.log('stderr:', String(err.stderr));
throw err;
try {
console.log('Creating final zip');
execSync(`cd ${tmpPath} && zip -ro ${zipFile} "${appName}"`);
} catch (err) {
console.log('stdout:', String(err.stdout));
console.log('stderr:', String(err.stderr));
throw err;
}
console.log('Moving into the final destination', zipPath);
fs.renameSync(path.join(tmpPath, zipFile), zipPath);
rimraf.sync(tmpPath);
}
console.log('Moving into the final destination', zipPath);
fs.renameSync(path.join(tmpPath, zipFile), zipPath);
rimraf.sync(tmpPath);
console.log('zip-macos-release is done');
}

View file

@ -24,13 +24,21 @@ releaseDate: '2019-03-29T16:58:08.210Z'
`);
const mac = parseYaml(`version: 1.23.2
files:
- url: signal-desktop-mac-1.23.2.zip
sha512: f4pPo3WulTVi9zBWGsJPNIlvPOTCxPibPPDmRFDoXMmFm6lqJpXZQ9DSWMJumfc4BRp4y/NTQLGYI6b4WuJwhg==
size: 105179791
blockMapSize: 111109
path: signal-desktop-mac-1.23.2.zip
sha512: f4pPo3WulTVi9zBWGsJPNIlvPOTCxPibPPDmRFDoXMmFm6lqJpXZQ9DSWMJumfc4BRp4y/NTQLGYI6b4WuJwhg==
releaseDate: '2019-03-29T16:57:16.997Z'
- url: signal-desktop-mac-x64-1.23.2.zip
sha512: STurwHhpE2rwwpwz3/RQBbMbVYY2Hh1DVpeofwIWPXoDTX/41zia+ByKXq8BvnjIMdQ3YmPHu+UppAW/+CFkFQ==
size: 150317727
- url: signal-desktop-mac-arm64-1.23.2.zip
sha512: PGFqCtiFep27rJcE3s8J2BAH9GQIRg460J0IVwbUCQERLZlN8YP71B1xWW09gCmA5YeEY4oDynqBLmgQfEFtfw==
size: 148022367
- url: signal-desktop-mac-x64-1.23.2.dmg
sha512: xbX5QDyzdvQd6rVzpamRLfWu+oIbhlW9pLbpKywQSiEx6BPZHTYCulBx9V5zrKh7TNM9nRpZJ3Sph2bU3v+5uQ==
size: 154866781
- url: signal-desktop-mac-arm64-1.23.2.dmg
sha512: 7wgGWCogQ9OWMGnqEUmiSeRct3w60zyzYp5cIUvJIVFe8WoB/qS7n721n+xCsrdteclR6yu1cqkOh/xN/wgS0Q==
size: 152618547
path: signal-desktop-mac-x64-1.23.2.zip
sha512: STurwHhpE2rwwpwz3/RQBbMbVYY2Hh1DVpeofwIWPXoDTX/41zia+ByKXq8BvnjIMdQ3YmPHu+UppAW/+CFkFQ==
releaseDate: '2021-12-03T19:00:23.754Z'
`);
const windowsBeta = parseYaml(`version: 1.23.2-beta.1
files:
@ -43,13 +51,21 @@ releaseDate: '2019-03-29T01:56:00.544Z'
`);
const macBeta = parseYaml(`version: 1.23.2-beta.1
files:
- url: signal-desktop-beta-mac-1.23.2-beta.1.zip
sha512: h/01N0DD5Jw2Q6M1n4uLGLTCrMFxcn8QOPtLR3HpABsf3w9b2jFtKb56/2cbuJXP8ol8TkTDWKnRV6mnqnLBDw==
size: 105182398
blockMapSize: 110894
path: signal-desktop-beta-mac-1.23.2-beta.1.zip
sha512: h/01N0DD5Jw2Q6M1n4uLGLTCrMFxcn8QOPtLR3HpABsf3w9b2jFtKb56/2cbuJXP8ol8TkTDWKnRV6mnqnLBDw==
releaseDate: '2019-03-29T01:53:23.881Z'
- url: signal-desktop-mac-x64-1.23.2-beta.1.zip
sha512: STurwHhpE2rwwpwz3/RQBbMbVYY2Hh1DVpeofwIWPXoDTX/41zia+ByKXq8BvnjIMdQ3YmPHu+UppAW/+CFkFQ==
size: 150317727
- url: signal-desktop-mac-arm64-1.23.2-beta.1.zip
sha512: PGFqCtiFep27rJcE3s8J2BAH9GQIRg460J0IVwbUCQERLZlN8YP71B1xWW09gCmA5YeEY4oDynqBLmgQfEFtfw==
size: 148022367
- url: signal-desktop-mac-x64-1.23.2-beta.1.dmg
sha512: xbX5QDyzdvQd6rVzpamRLfWu+oIbhlW9pLbpKywQSiEx6BPZHTYCulBx9V5zrKh7TNM9nRpZJ3Sph2bU3v+5uQ==
size: 154866781
- url: signal-desktop-mac-arm64-1.23.2-beta.1.dmg
sha512: 7wgGWCogQ9OWMGnqEUmiSeRct3w60zyzYp5cIUvJIVFe8WoB/qS7n721n+xCsrdteclR6yu1cqkOh/xN/wgS0Q==
size: 152618547
path: signal-desktop-mac-x64-1.23.2-beta.1.zip
sha512: STurwHhpE2rwwpwz3/RQBbMbVYY2Hh1DVpeofwIWPXoDTX/41zia+ByKXq8BvnjIMdQ3YmPHu+UppAW/+CFkFQ==
releaseDate: '2021-12-03T19:00:23.754Z'
`);
describe('#getVersion', () => {
@ -67,20 +83,28 @@ releaseDate: '2019-03-29T01:53:23.881Z'
describe('#getUpdateFileName', () => {
it('successfully gets version', () => {
assert.strictEqual(
getUpdateFileName(windows),
getUpdateFileName(windows, 'win32', 'x64'),
'signal-desktop-win-1.23.2.exe'
);
assert.strictEqual(
getUpdateFileName(mac),
'signal-desktop-mac-1.23.2.zip'
getUpdateFileName(mac, 'darwin', 'x64'),
'signal-desktop-mac-x64-1.23.2.zip'
);
assert.strictEqual(
getUpdateFileName(windowsBeta),
getUpdateFileName(mac, 'darwin', 'arm64'),
'signal-desktop-mac-arm64-1.23.2.zip'
);
assert.strictEqual(
getUpdateFileName(windowsBeta, 'win32', 'x64'),
'signal-desktop-beta-win-1.23.2-beta.1.exe'
);
assert.strictEqual(
getUpdateFileName(macBeta),
'signal-desktop-beta-mac-1.23.2-beta.1.zip'
getUpdateFileName(macBeta, 'darwin', 'x64'),
'signal-desktop-mac-x64-1.23.2-beta.1.zip'
);
assert.strictEqual(
getUpdateFileName(macBeta, 'darwin', 'arm64'),
'signal-desktop-mac-arm64-1.23.2-beta.1.zip'
);
});
});
@ -92,7 +116,7 @@ releaseDate: '2019-03-29T01:53:23.881Z'
true
);
assert.strictEqual(
isUpdateFileNameValid('signal-desktop-mac-1.23.2-beta.1.zip'),
isUpdateFileNameValid('signal-desktop-mac-x64-1.23.2-beta.1.zip'),
true
);
});
@ -102,11 +126,11 @@ releaseDate: '2019-03-29T01:53:23.881Z'
false
);
assert.strictEqual(
isUpdateFileNameValid('%signal-desktop-mac-1.23.2-beta.1.zip'),
isUpdateFileNameValid('%signal-desktop-mac-x64-1.23.2-beta.1.zip'),
false
);
assert.strictEqual(
isUpdateFileNameValid('@signal-desktop-mac-1.23.2-beta.1.zip'),
isUpdateFileNameValid('@signal-desktop-mac-x64-1.23.2-beta.1.zip'),
false
);
});

View file

@ -7,6 +7,8 @@ import {
statSync,
writeFile as writeFileCallback,
} from 'fs';
import { promisify } from 'util';
import { execFile } from 'child_process';
import { join, normalize, dirname } from 'path';
import { tmpdir } from 'os';
import { throttle } from 'lodash';
@ -47,7 +49,6 @@ import type { LoggerType } from '../types/Logging';
const writeFile = pify(writeFileCallback);
const mkdirpPromise = pify(mkdirp);
const rimrafPromise = pify(rimraf);
const { platform } = process;
export const GOT_CONNECT_TIMEOUT = 2 * 60 * 1000;
export const GOT_LOOKUP_TIMEOUT = 2 * 60 * 1000;
@ -267,7 +268,11 @@ export abstract class Updater {
`forceUpdate=${forceUpdate}`
);
const fileName = getUpdateFileName(parsedYaml);
const fileName = getUpdateFileName(
parsedYaml,
process.platform,
await this.getArch()
);
return {
fileName,
@ -377,6 +382,27 @@ export abstract class Updater {
this.logger.error(`quitHandler: ${Errors.toLogFormat(error)}`);
}
}
private async getArch(): Promise<typeof process.arch> {
if (process.platform !== 'darwin' || process.arch === 'arm64') {
return process.arch;
}
try {
// We might be running under Rosetta
if (promisify(execFile)('uname', ['-m']).toString().trim() === 'arm64') {
this.logger.info('updater: running under Rosetta');
return 'arm64';
}
} catch (error) {
this.logger.warn(
`updater: "uname -m" failed with ${Errors.toLogFormat(error)}`
);
}
this.logger.info('updater: not running under Rosetta');
return process.arch;
}
}
export function validatePath(basePath: string, targetPath: string): void {
@ -408,7 +434,7 @@ export function getProxyUrl(): string | undefined {
export function getUpdatesFileName(): string {
const prefix = getChannel();
if (platform === 'darwin') {
if (process.platform === 'darwin') {
return `${prefix}-mac.yml`;
}
@ -442,12 +468,30 @@ export function isUpdateFileNameValid(name: string): boolean {
return validFile.test(name);
}
export function getUpdateFileName(info: JSONUpdateSchema): string {
export function getUpdateFileName(
info: JSONUpdateSchema,
platform: typeof process.platform,
arch: typeof process.arch
): string {
if (!info || !info.path) {
throw new Error('getUpdateFileName: No path present in YAML file');
}
const { path } = info;
let path: string | undefined;
if (platform === 'darwin') {
const { files } = info;
const candidates = files.filter(
({ url }) => url.includes(arch) && url.endsWith('.zip')
);
if (candidates.length === 1) {
path = candidates[0].url;
}
}
path = path ?? info.path;
if (!isUpdateFileNameValid(path)) {
throw new Error(
`getUpdateFileName: Path '${path}' contains invalid characters`

View file

@ -52,35 +52,46 @@ go(cliOptions).catch(error => {
async function go(options: OptionsType) {
const { private: privateKeyPath, version } = options;
let { update: updatePath } = options;
if (!updatePath) {
updatePath = await findUpdatePath();
let updatePaths: Array<string>;
if (options.update) {
updatePaths = [options.update];
} else {
updatePaths = await findUpdatePaths();
}
console.log('Signing with...');
console.log(` version: ${version}`);
console.log(` update file: ${updatePath}`);
console.log(` private key file: ${privateKeyPath}`);
await Promise.all(
updatePaths.map(async updatePath => {
console.log('Signing with...');
console.log(` version: ${version}`);
console.log(` update file: ${updatePath}`);
console.log(` private key file: ${privateKeyPath}`);
await writeSignature(updatePath, version, privateKeyPath);
await writeSignature(updatePath, version, privateKeyPath);
})
);
}
const IS_EXE = /\.exe$/;
const IS_ZIP = /\.zip$/;
async function findUpdatePath(): Promise<string> {
async function findUpdatePaths(): Promise<Array<string>> {
const releaseDir = resolve('release');
const files: Array<string> = await readdir(releaseDir);
const max = files.length;
const results = new Array<string>();
for (let i = 0; i < max; i += 1) {
const file = files[i];
const fullPath = join(releaseDir, file);
if (IS_EXE.test(file) || IS_ZIP.test(file)) {
return fullPath;
results.push(fullPath);
}
}
throw new Error("No suitable file found in 'release' folder!");
if (results.length === 0) {
throw new Error("No suitable file found in 'release' folder!");
}
return results;
}