// @ts-check 'use strict'; const semver = require('semver'); const { isNightly, isRelease } = require('./utils'); async function run() { /** @type {string} */ const electronVersion = require('../package.json').devDependencies['electron']; const platform = electronPlatform(); const version = await getVersion(); /** @type {string|unknown} */ const cliVersion = require('../../arduino-ide-extension/package.json') .arduino['arduino-cli'].version; const artifactName = await getArtifactName(version); const args = [ '--publish', 'never', '-c.electronVersion', electronVersion.slice(1), // removes the leading ^ from the version. TODO: user `semver` to clean it. '-c.extraMetadata.version', version, // overrides the `name` in the `package.json` to keep the `localStorage` location. (https://github.com/arduino/arduino-ide/pull/2144#pullrequestreview-1554005028) '-c.extraMetadata.name', 'arduino-ide', `-c.${platform}.artifactName`, artifactName, '-c.extraMetadata.theia.frontend.config.appVersion', version, '-c.extraMetadata.theia.frontend.config.cliVersion', typeof cliVersion === 'string' ? cliVersion : '', '-c.extraMetadata.theia.frontend.config.buildDate', new Date().toISOString(), // when running in development mode, the main entry is a JS module generated by Theia. In the final application it's a custom module with the file logger. '-c.extraMetadata.main', './arduino-ide-electron-main.js', ]; const updateChannel = getChannel(); if (updateChannel) { // TODO: fix the default nightly update channel preference value if required. // It's disabled for now: https://github.com/arduino/arduino-ide/issues/2157. // args.push( // '-c.extraMetadata.theia.frontend.config.arduino.ide.updateChannel', // updateChannel // ); } const cp = exec('electron-builder', args, { stdio: 'inherit' }); await cp; } function electronPlatform() { switch (process.platform) { case 'win32': { return 'win'; } case 'darwin': { return 'mac'; } case 'linux': { return 'linux'; } default: throw new Error(`Unsupported platform: ${process.platform}.`); } } /** * @returns {Promise} */ async function getVersion() { /** @type {string} */ let version = require('../package.json').version; if (!semver.valid(version)) { throw new Error( `Could not read version from root package.json. Version was: '${version}'.` ); } if (!isRelease) { if (isNightly) { version = `${version}-nightly-${await timestamp()}`; } else { version = `${version}-snapshot-${await currentCommitish()}`; } if (!semver.valid(version)) { throw new Error(`Invalid patched version: '${version}'.`); } } return version; } /** * @param {string} version * @returns {Promise} */ async function getArtifactName(version) { const { platform, arch } = process; version = isNightly ? `nightly-${await timestamp()}` : version; const name = 'arduino-ide'; switch (platform) { case 'win32': { if (arch === 'x64') { return `${name}_${version}_Windows_64bit.\$\{ext}`; } throw new Error(`Unsupported platform, arch: ${platform}, ${arch}`); } case 'darwin': { if (arch === 'arm64') { return `${name}_${version}_macOS_arm64.\$\{ext}`; } return `${name}_${version}_macOS_64bit.\$\{ext}`; } case 'linux': { switch (arch) { case 'arm': { return `${name}_${version}_Linux_armv7.\$\{ext}`; } case 'arm64': { return `${name}_${version}_Linux_arm64.\$\{ext}`; } case 'x64': { return `${name}_${version}_Linux_64bit.\$\{ext}`; } default: { throw new Error(`Unsupported platform, arch: ${platform}, ${arch}`); } } } default: throw new Error(`Unsupported platform, arch: ${platform}, ${arch}`); } } function getChannel() { if (isRelease) { return 'stable'; } if (isNightly) { return 'nightly'; } return ''; } async function timestamp() { const { default: dateFormat } = await import('dateformat'); return dateFormat(new Date(), 'yyyymmdd'); } async function currentCommitish() { return exec('git', ['rev-parse', '--short', 'HEAD']); } /** * @param {string} command * @param {readonly string[]} args * @param {import('execa').Options | undefined} [options] * @returns {Promise} */ async function exec(command, args, options) { const execa = await import('execa'); const promise = execa.execa(command, args, options); const { stdout } = await promise; return stdout; } run();