/* eslint-disable no-sync */ import * as cp from 'child_process' import * as path from 'path' import * as electronInstaller from 'electron-winstaller' import { getProductName, getCompanyName } from '../app/package-info' import { getDistPath, getOSXZipPath, getWindowsIdentifierName, getWindowsStandaloneName, getWindowsInstallerName, shouldMakeDelta, getUpdatesURL, getIconFileName, isPublishable, getBundleSizes, getDistRoot, getDistArchitecture, } from './dist-info' import { isGitHubActions } from './build-platforms' import { existsSync, rmSync, writeFileSync } from 'fs' import { getVersion } from '../app/package-info' import { rename } from 'fs/promises' import { join } from 'path' import { assertNonNullable } from '../app/src/lib/fatal-error' const distPath = getDistPath() const productName = getProductName() const outputDir = getDistRoot() if (process.platform === 'darwin') { packageOSX() } else if (process.platform === 'win32') { packageWindows() } else { console.error(`I don't know how to package for ${process.platform} :(`) process.exit(1) } console.log('Writing bundle size info…') writeFileSync( path.join(getDistRoot(), 'bundle-size.json'), JSON.stringify(getBundleSizes()) ) function packageOSX() { const dest = getOSXZipPath() rmSync(dest, { recursive: true, force: true }) console.log('Packaging for macOS…') cp.execSync( `ditto -ck --keepParent "${distPath}/${productName}.app" "${dest}"` ) } function packageWindows() { const iconSource = path.join( __dirname, '..', 'app', 'static', 'logos', `${getIconFileName()}.ico` ) if (!existsSync(iconSource)) { console.error(`expected setup icon not found at location: ${iconSource}`) process.exit(1) } const splashScreenPath = path.resolve( __dirname, '../app/static/logos/win32-installer-splash.gif' ) if (!existsSync(splashScreenPath)) { console.error( `expected setup splash screen gif not found at location: ${splashScreenPath}` ) process.exit(1) } const iconUrl = 'https://desktop.githubusercontent.com/github-desktop/app-icon.ico' const nugetPkgName = getWindowsIdentifierName() const options: electronInstaller.Options = { name: nugetPkgName, appDirectory: distPath, outputDirectory: outputDir, authors: getCompanyName(), iconUrl: iconUrl, setupIcon: iconSource, loadingGif: splashScreenPath, exe: `${nugetPkgName}.exe`, title: productName, setupExe: getWindowsStandaloneName(), setupMsi: getWindowsInstallerName(), } if (shouldMakeDelta()) { const url = new URL(getUpdatesURL()) // Make sure Squirrel.Windows isn't affected by partially or completely // disabled releases. url.searchParams.set('bypassStaggeredRelease', '1') options.remoteReleases = url.toString() } if (isGitHubActions() && isPublishable()) { assertNonNullable(process.env.RUNNER_TEMP, 'Missing RUNNER_TEMP env var') const acsPath = join(process.env.RUNNER_TEMP, 'acs') const dlibPath = join( acsPath, 'Azure.CodeSigning.Client.1.0.38', 'bin', 'x64', 'Azure.CodeSigning.Dlib.dll' ) const metadataPath = join(acsPath, 'acs-metadata.json') const acsMetadata = { Endpoint: 'https://eus.codesigning.azure.net/', CodeSigningAccountName: 'github-desktop', CertificateProfileName: 'desktop', CorrelationId: `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}`, } writeFileSync(metadataPath, JSON.stringify(acsMetadata, null, 2), 'utf8') options.signWithParams = `/v /debug /fd SHA256 /tr "http://timestamp.acs.microsoft.com" /td SHA256 /dlib "${dlibPath}" /dmdf "${metadataPath}"` } console.log('Packaging for Windows…') electronInstaller .createWindowsInstaller(options) .then(() => console.log(`Installers created in ${outputDir}`)) .then(async () => { // electron-winstaller (more specifically Squirrel.Windows) doesn't let // us control the name of the nuget packages but we want them to include // the architecture similar to how the setup exe and msi do so we'll just // have to rename them here after the fact. const arch = getDistArchitecture() const prefix = `${getWindowsIdentifierName()}-${getVersion()}` for (const kind of shouldMakeDelta() ? ['full', 'delta'] : ['full']) { const from = join(outputDir, `${prefix}-${kind}.nupkg`) const to = join(outputDir, `${prefix}-${arch}-${kind}.nupkg`) console.log(`Renaming ${from} to ${to}`) await rename(from, to) } }) .catch(e => { console.error(`Error packaging: ${e}`) process.exit(1) }) }