diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d0bdd278a..25dbc8b2e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -60,9 +60,7 @@ jobs: if [ $IS_FORK = true ]; then echo "Skipping the app signing: building from a fork." else - export BUILD_SUFFIX="linux"; if [ "${{ runner.OS }}" = "macOS" ]; then - export BUILD_SUFFIX="mac"; export CSC_LINK="${{ runner.temp }}/signing_certificate.p12" # APPLE_SIGNING_CERTIFICATE_P12 secret was produced by following the procedure from: # https://www.kencochrane.com/2020/08/01/build-and-sign-golang-binaries-for-macos-with-github-actions/#exporting-the-developer-certificate @@ -71,7 +69,6 @@ jobs: export CSC_KEY_PASSWORD="${{ secrets.KEYCHAIN_PASSWORD }}" elif [ "${{ runner.OS }}" = "Windows" ]; then - export BUILD_SUFFIX=""; export CSC_LINK="${{ runner.temp }}/signing_certificate.pfx" npm config set msvs_version 2017 --global echo "${{ secrets.WINDOWS_SIGNING_CERTIFICATE_PFX }}" | base64 --decode > "$CSC_LINK" @@ -81,15 +78,7 @@ jobs: fi yarn --cwd ./electron/packager/ - yarn --cwd ./electron/packager/ package - - export BUILD_PREFIX="stable" - if [ "$IS_NIGHTLY" = true ]; then - export BUILD_PREFIX="nightly" - fi - - mv electron/build/dist/latest-$BUILD_SUFFIX.yml electron/build/dist/$BUILD_PREFIX-$BUILD_SUFFIX.yml - rm electron/build/dist/alpha* electron/build/dist/beta* + yarn --cwd ./electron/packager/ package - name: Upload [GitHub Actions] uses: actions/upload-artifact@v2 diff --git a/electron/packager/config.js b/electron/packager/config.js index e74d9d84d..5b2aeeaa1 100644 --- a/electron/packager/config.js +++ b/electron/packager/config.js @@ -106,7 +106,7 @@ function getChannel() { return 'nightly'; } - return 'none'; + return ''; } function timestamp() { diff --git a/electron/packager/index.js b/electron/packager/index.js index 17fc272a7..5fc213164 100644 --- a/electron/packager/index.js +++ b/electron/packager/index.js @@ -1,347 +1,440 @@ //@ts-check (async () => { - - const fs = require('fs'); - const join = require('path').join; - const shell = require('shelljs'); - const glob = require('glob'); - const isCI = require('is-ci'); - shell.env.THEIA_ELECTRON_SKIP_REPLACE_FFMPEG = '1'; // Do not run the ffmpeg validation for the packager. - shell.env.NODE_OPTIONS = '--max_old_space_size=4096'; // Increase heap size for the CI - shell.env.PUPPETEER_SKIP_CHROMIUM_DOWNLOAD = 'true'; // Skip download and avoid `ERROR: Failed to download Chromium`. - const template = require('./config').generateTemplate(new Date().toISOString()); - const utils = require('./utils'); - const merge = require('deepmerge'); - const { isRelease, isElectronPublish, getChannelFile } = utils; - const { version } = template; - const { productName } = template.build; - - echo(`📦 Building ${isRelease ? 'release ' : ''}version '${version}'...`); - - const workingCopy = 'working-copy'; - - /** - * Relative path from the `__dirname` to the root where the `arduino-ide-extension` and the `electron-app` folders are. - * This could come handy when moving the location of the `electron/packager`. - */ - const rootPath = join('..', '..'); - - // This is a HACK! We rename the root `node_modules` to something else. Otherwise, due to the hoisting, - // multiple Theia extensions will be picked up. - if (fs.existsSync(path(rootPath, 'node_modules'))) { - // We either do this or change the project structure. - echo('🔧 >>> [Hack] Renaming the root \'node_modules\' folder to \'.node_modules\'...'); - mv('-f', path(rootPath, 'node_modules'), path(rootPath, '.node_modules')); - echo('👌 <<< [Hack] Renamed the root \'node_modules\' folder to \'.node_modules\'.') - } - - //---------------------------+ - // Clean the previous state. | - //---------------------------+ - // rm -rf ../working-copy - rm('-rf', path('..', workingCopy)); - // Clean up the `./electron/build` folder. - const resourcesToKeep = ['patch', 'resources', 'scripts', 'template-package.json']; - for (const filename of fs.readdirSync(path('..', 'build')).filter(filename => resourcesToKeep.indexOf(filename) === -1)) { - rm('-rf', path('..', 'build', filename)); - } - - const extensions = require('./extensions.json'); - echo(`Building the application with the following extensions:\n${extensions.map(ext => ` - ${ext}`).join(',\n')}`); - const allDependencies = [ - ...extensions, - 'electron-app' - ] - - //----------------------------------------------------------------------------------------------+ - // Copy the following items into the `working-copy` folder. Make sure to reuse the `yarn.lock`. | - //----------------------------------------------------------------------------------------------+ - mkdir('-p', path('..', workingCopy)); - for (const name of [...allDependencies, 'yarn.lock', 'package.json', 'lerna.json']) { - cp('-rf', path(rootPath, name), path('..', workingCopy)); - } - - //----------------------------------------------+ - // Sanity check: all versions must be the same. | - //----------------------------------------------+ - verifyVersions(allDependencies); - //----------------------------------------------------------------------+ - // Use the nightly patch version if not a release but requires publish. | - //----------------------------------------------------------------------+ - if (!isRelease) { - for (const dependency of allDependencies) { - const pkg = require(`../working-copy/${dependency}/package.json`); - pkg.version = version; - for (const dependency in pkg.dependencies) { - if (allDependencies.indexOf(dependency) !== -1) { - pkg.dependencies[dependency] = version; - } - } - fs.writeFileSync(path('..', workingCopy, dependency, 'package.json'), JSON.stringify(pkg, null, 2)); - } - } - verifyVersions(allDependencies); - - //-------------------------------------------------------------+ - // Save some time: no need to build the `browser-app` example. | - //-------------------------------------------------------------+ - //@ts-ignore - let pkg = require('../working-copy/package.json'); - const workspaces = pkg.workspaces; - // We cannot remove the `electron-app`. Otherwise, there is not way to collect the unused dependencies. - const dependenciesToRemove = ['browser-app']; - for (const dependencyToRemove of dependenciesToRemove) { - const index = workspaces.indexOf(dependencyToRemove); - if (index !== -1) { - workspaces.splice(index, 1); + const fs = require('fs'); + const join = require('path').join; + const shell = require('shelljs'); + const glob = require('glob'); + const isCI = require('is-ci'); + shell.env.THEIA_ELECTRON_SKIP_REPLACE_FFMPEG = '1'; // Do not run the ffmpeg validation for the packager. + shell.env.NODE_OPTIONS = '--max_old_space_size=4096'; // Increase heap size for the CI + shell.env.PUPPETEER_SKIP_CHROMIUM_DOWNLOAD = 'true'; // Skip download and avoid `ERROR: Failed to download Chromium`. + const template = require('./config').generateTemplate( + new Date().toISOString() + ); + const utils = require('./utils'); + const merge = require('deepmerge'); + const { isRelease, isElectronPublish, getChannelFile } = utils; + const { version } = template; + const { productName } = template.build; + + echo(`📦 Building ${isRelease ? 'release ' : ''}version '${version}'...`); + + const workingCopy = 'working-copy'; + + /** + * Relative path from the `__dirname` to the root where the `arduino-ide-extension` and the `electron-app` folders are. + * This could come handy when moving the location of the `electron/packager`. + */ + const rootPath = join('..', '..'); + + // This is a HACK! We rename the root `node_modules` to something else. Otherwise, due to the hoisting, + // multiple Theia extensions will be picked up. + if (fs.existsSync(path(rootPath, 'node_modules'))) { + // We either do this or change the project structure. + echo( + "🔧 >>> [Hack] Renaming the root 'node_modules' folder to '.node_modules'..." + ); + mv('-f', path(rootPath, 'node_modules'), path(rootPath, '.node_modules')); + echo( + "👌 <<< [Hack] Renamed the root 'node_modules' folder to '.node_modules'." + ); + } + + //---------------------------+ + // Clean the previous state. | + //---------------------------+ + // rm -rf ../working-copy + rm('-rf', path('..', workingCopy)); + // Clean up the `./electron/build` folder. + const resourcesToKeep = [ + 'patch', + 'resources', + 'scripts', + 'template-package.json', + ]; + fs.readdirSync(path('..', 'build')) + .filter((filename) => resourcesToKeep.indexOf(filename) === -1) + .forEach((filename) => rm('-rf', path('..', 'build', filename))); + + const extensions = require('./extensions.json'); + echo( + `Building the application with the following extensions:\n${extensions + .map((ext) => ` - ${ext}`) + .join(',\n')}` + ); + const allDependencies = [...extensions, 'electron-app']; + + //----------------------------------------------------------------------------------------------+ + // Copy the following items into the `working-copy` folder. Make sure to reuse the `yarn.lock`. | + //----------------------------------------------------------------------------------------------+ + mkdir('-p', path('..', workingCopy)); + for (const name of [ + ...allDependencies, + 'yarn.lock', + 'package.json', + 'lerna.json', + ]) { + cp('-rf', path(rootPath, name), path('..', workingCopy)); + } + + //----------------------------------------------+ + // Sanity check: all versions must be the same. | + //----------------------------------------------+ + verifyVersions(allDependencies); + //----------------------------------------------------------------------+ + // Use the nightly patch version if not a release but requires publish. | + //----------------------------------------------------------------------+ + if (!isRelease) { + for (const dependency of allDependencies) { + const pkg = require(`../working-copy/${dependency}/package.json`); + pkg.version = version; + for (const dependency in pkg.dependencies) { + if (allDependencies.indexOf(dependency) !== -1) { + pkg.dependencies[dependency] = version; } + } + fs.writeFileSync( + path('..', workingCopy, dependency, 'package.json'), + JSON.stringify(pkg, null, 2) + ); } - pkg.workspaces = workspaces; - fs.writeFileSync(path('..', workingCopy, 'package.json'), JSON.stringify(pkg, null, 2)); - - //-------------------------------------------------------------------------------------------------+ - // Rebuild the extension with the copied `yarn.lock`. It is a must to use the same Theia versions. | - //-------------------------------------------------------------------------------------------------+ - exec(`yarn --network-timeout 1000000 --cwd ${path('..', workingCopy)}`, `Building the ${productName} application`); - - //-------------------------------------------------------------------------------------------------------------------------+ - // Test the application. With this approach, we cannot publish test results to GH Actions but save 6-10 minutes per builds | - //-------------------------------------------------------------------------------------------------------------------------+ - exec(`yarn --network-timeout 1000000 --cwd ${path('..', workingCopy)} test`, `Testing the ${productName} application`); - - // Collect all unused dependencies by the backend. We have to remove them from the electron app. - // The `bundle.js` already contains everything we need for the frontend. - // We have to do it before changing the dependencies to `local-path`. - const unusedDependencies = await utils.collectUnusedDependencies('../working-copy/electron-app/'); - - //-------------------------------------------------------------------------------------------------------------+ - // Change the regular NPM dependencies to `local-paths`, so that we can build them without any NPM registries. | - //-------------------------------------------------------------------------------------------------------------+ - for (const extension of extensions) { - if (extension !== 'arduino-ide-extension') { // Do not unlink self. - // @ts-ignore - pkg = require(`../working-copy/${extension}/package.json`); - // @ts-ignore - pkg.dependencies['arduino-ide-extension'] = 'file:../arduino-ide-extension'; - fs.writeFileSync(path('..', workingCopy, extension, 'package.json'), JSON.stringify(pkg, null, 2)); - } + } + verifyVersions(allDependencies); + + //-------------------------------------------------------------+ + // Save some time: no need to build the `browser-app` example. | + //-------------------------------------------------------------+ + //@ts-ignore + let pkg = require('../working-copy/package.json'); + const workspaces = pkg.workspaces; + // We cannot remove the `electron-app`. Otherwise, there is not way to collect the unused dependencies. + const dependenciesToRemove = ['browser-app']; + for (const dependencyToRemove of dependenciesToRemove) { + const index = workspaces.indexOf(dependencyToRemove); + if (index !== -1) { + workspaces.splice(index, 1); } - - //------------------------------------------------------------------------------------+ - // Merge the `working-copy/package.json` with `electron/build/template-package.json`. | - //------------------------------------------------------------------------------------+ - // @ts-ignore - pkg = require('../working-copy/electron-app/package.json'); - template.build.files = [...template.build.files, ...unusedDependencies.map(name => `!node_modules/${name}`)]; - - const dependencies = {}; - for (const extension of extensions) { - dependencies[extension] = `file:../working-copy/${extension}`; + } + pkg.workspaces = workspaces; + fs.writeFileSync( + path('..', workingCopy, 'package.json'), + JSON.stringify(pkg, null, 2) + ); + + //-------------------------------------------------------------------------------------------------+ + // Rebuild the extension with the copied `yarn.lock`. It is a must to use the same Theia versions. | + //-------------------------------------------------------------------------------------------------+ + exec( + `yarn --network-timeout 1000000 --cwd ${path('..', workingCopy)}`, + `Building the ${productName} application` + ); + + //-------------------------------------------------------------------------------------------------------------------------+ + // Test the application. With this approach, we cannot publish test results to GH Actions but save 6-10 minutes per builds | + //-------------------------------------------------------------------------------------------------------------------------+ + exec( + `yarn --network-timeout 1000000 --cwd ${path('..', workingCopy)} test`, + `Testing the ${productName} application` + ); + + // Collect all unused dependencies by the backend. We have to remove them from the electron app. + // The `bundle.js` already contains everything we need for the frontend. + // We have to do it before changing the dependencies to `local-path`. + const unusedDependencies = await utils.collectUnusedDependencies( + '../working-copy/electron-app/' + ); + + //-------------------------------------------------------------------------------------------------------------+ + // Change the regular NPM dependencies to `local-paths`, so that we can build them without any NPM registries. | + //-------------------------------------------------------------------------------------------------------------+ + for (const extension of extensions) { + if (extension !== 'arduino-ide-extension') { + // Do not unlink self. + // @ts-ignore + pkg = require(`../working-copy/${extension}/package.json`); + // @ts-ignore + pkg.dependencies['arduino-ide-extension'] = + 'file:../arduino-ide-extension'; + fs.writeFileSync( + path('..', workingCopy, extension, 'package.json'), + JSON.stringify(pkg, null, 2) + ); } + } + + //------------------------------------------------------------------------------------+ + // Merge the `working-copy/package.json` with `electron/build/template-package.json`. | + //------------------------------------------------------------------------------------+ + // @ts-ignore + pkg = require('../working-copy/electron-app/package.json'); + template.build.files = [ + ...template.build.files, + ...unusedDependencies.map((name) => `!node_modules/${name}`), + ]; + + const dependencies = {}; + for (const extension of extensions) { + dependencies[extension] = `file:../working-copy/${extension}`; + } + // @ts-ignore + pkg.dependencies = { ...pkg.dependencies, ...dependencies }; + pkg.devDependencies = { ...pkg.devDependencies, ...template.devDependencies }; + // Deep-merging the Theia application configuration. We enable the electron window reload in dev mode but not for the final product. (arduino/arduino-pro-ide#187) + // @ts-ignore + const theia = merge(pkg.theia || {}, template.theia || {}); + const content = { + ...pkg, + ...template, + theia, // @ts-ignore - pkg.dependencies = { ...pkg.dependencies, ...dependencies }; - pkg.devDependencies = { ...pkg.devDependencies, ...template.devDependencies }; - // Deep-merging the Theia application configuration. We enable the electron window reload in dev mode but not for the final product. (arduino/arduino-pro-ide#187) - // @ts-ignore - const theia = merge((pkg.theia || {}), (template.theia || {})); - const content = { - ...pkg, - ...template, - theia, - // @ts-ignore - dependencies: pkg.dependencies, - devDependencies: pkg.devDependencies - }; - const overwriteMerge = (destinationArray, sourceArray, options) => sourceArray; - fs.writeFileSync(path('..', 'build', 'package.json'), JSON.stringify(merge(content, template, { arrayMerge: overwriteMerge }), null, 2)); - - echo(`📜 Effective 'package.json' for the ${productName} application is: + dependencies: pkg.dependencies, + devDependencies: pkg.devDependencies, + }; + const overwriteMerge = (destinationArray, sourceArray, options) => + sourceArray; + fs.writeFileSync( + path('..', 'build', 'package.json'), + JSON.stringify( + merge(content, template, { arrayMerge: overwriteMerge }), + null, + 2 + ) + ); + + echo(`📜 Effective 'package.json' for the ${productName} application is: ----------------------- ${fs.readFileSync(path('..', 'build', 'package.json')).toString()} ----------------------- `); - // Make sure the original `yarn.lock` file is used from the electron application. - if (fs.existsSync(path('..', 'build', 'yarn.lock'))) { - echo(`${path('..', 'build', 'yarn.lock')} must not exist.`); - shell.exit(1); - } - cp('-rf', path(rootPath, 'yarn.lock'), path('..', 'build')); - if (!fs.existsSync(path('..', 'build', 'yarn.lock'))) { - echo(`${path('..', 'build', 'yarn.lock')} does not exist.`); - shell.exit(1); - } - - //-------------------------------------------------------------------------------------------+ - // Install all private and public dependencies for the electron application and build Theia. | - //-------------------------------------------------------------------------------------------+ - exec(`yarn --network-timeout 1000000 --cwd ${path('..', 'build')}`, 'Installing dependencies'); - exec(`yarn --network-timeout 1000000 --cwd ${path('..', 'build')} build${isElectronPublish ? ':publish' : ''}`, `Building the ${productName} application`); - exec(`yarn --network-timeout 1000000 --cwd ${path('..', 'build')} rebuild`, 'Rebuild native dependencies'); - - //------------------------------------------------------------------------------+ - // Create a throw away dotenv file which we use to feed the builder with input. | - //------------------------------------------------------------------------------+ - const dotenv = 'electron-builder.env'; - if (fs.existsSync(path('..', 'build', dotenv))) { - rm('-rf', path('..', 'build', dotenv)); - } - // For the releases we use the desired tag as is defined by `$(Release.Tag)` from Azure. - // For the preview builds we use the version from the `electron/build/package.json` with the short commit hash. - fs.writeFileSync(path('..', 'build', dotenv), `ARDUINO_VERSION=${version}`); - - //-----------------------------------+ - // Package the electron application. | - //-----------------------------------+ - exec(`yarn --network-timeout 1000000 --cwd ${path('..', 'build')} package`, `Packaging your ${productName} application`); - - //-----------------------------------------------------------------------------------------------------+ - // Copy to another folder. Azure does not support wildcard for `PublishBuildArtifacts@1.pathToPublish` | - //-----------------------------------------------------------------------------------------------------+ - if (isCI) { - try { - await copyFilesToBuildArtifacts(); - } catch (e) { - echo(JSON.stringify(e)); - shell.exit(1); - } + // Make sure the original `yarn.lock` file is used from the electron application. + if (fs.existsSync(path('..', 'build', 'yarn.lock'))) { + echo(`${path('..', 'build', 'yarn.lock')} must not exist.`); + shell.exit(1); + } + cp('-rf', path(rootPath, 'yarn.lock'), path('..', 'build')); + if (!fs.existsSync(path('..', 'build', 'yarn.lock'))) { + echo(`${path('..', 'build', 'yarn.lock')} does not exist.`); + shell.exit(1); + } + + //-------------------------------------------------------------------------------------------+ + // Install all private and public dependencies for the electron application and build Theia. | + //-------------------------------------------------------------------------------------------+ + exec( + `yarn --network-timeout 1000000 --cwd ${path('..', 'build')}`, + 'Installing dependencies' + ); + exec( + `yarn --network-timeout 1000000 --cwd ${path('..', 'build')} build${ + isElectronPublish ? ':publish' : '' + }`, + `Building the ${productName} application` + ); + exec( + `yarn --network-timeout 1000000 --cwd ${path('..', 'build')} rebuild`, + 'Rebuild native dependencies' + ); + + //------------------------------------------------------------------------------+ + // Create a throw away dotenv file which we use to feed the builder with input. | + //------------------------------------------------------------------------------+ + const dotenv = 'electron-builder.env'; + if (fs.existsSync(path('..', 'build', dotenv))) { + rm('-rf', path('..', 'build', dotenv)); + } + // For the releases we use the desired tag as is defined by `$(Release.Tag)` from Azure. + // For the preview builds we use the version from the `electron/build/package.json` with the short commit hash. + fs.writeFileSync(path('..', 'build', dotenv), `ARDUINO_VERSION=${version}`); + + //-----------------------------------+ + // Package the electron application. | + //-----------------------------------+ + exec( + `yarn --network-timeout 1000000 --cwd ${path('..', 'build')} package`, + `Packaging your ${productName} application` + ); + + //-----------------------------------------------------------------------------------------------------+ + // Copy to another folder. Azure does not support wildcard for `PublishBuildArtifacts@1.pathToPublish` | + //-----------------------------------------------------------------------------------------------------+ + if (isCI) { + try { + await copyFilesToBuildArtifacts(); + } catch (e) { + echo(JSON.stringify(e)); + shell.exit(1); } - echo(`🎉 Success. Your application is at: ${path('..', 'build', 'dist')}`); + } + echo(`🎉 Success. Your application is at: ${path('..', 'build', 'dist')}`); - restore(); + restore(); - //--------+ - // Utils. | - //--------+ - function exec(command, toEcho) { - if (toEcho) { - echo(`⏱️ >>> ${toEcho}...`); - } - const { code, stderr, stdout } = shell.exec(command); - if (code !== 0) { - echo(`🔥 Error when executing ${command} => ${stderr}`); - shell.exit(1); - } - if (toEcho) { - echo(`👌 <<< ${toEcho}.`); - } - return stdout; + //--------+ + // Utils. | + //--------+ + function exec(command, toEcho) { + if (toEcho) { + echo(`⏱️ >>> ${toEcho}...`); } - - function cp(options, source, destination) { - shell.cp(options, source, destination); - assertNoError(); + const { code, stderr, stdout } = shell.exec(command); + if (code !== 0) { + echo(`🔥 Error when executing ${command} => ${stderr}`); + shell.exit(1); } - - function rm(options, ...files) { - shell.rm(options, files); - assertNoError(); + if (toEcho) { + echo(`👌 <<< ${toEcho}.`); } - - function mv(options, source, destination) { - shell.mv(options, source, destination); - assertNoError(); + return stdout; + } + + function cp(options, source, destination) { + shell.cp(options, source, destination); + assertNoError(); + } + + function rm(options, ...files) { + shell.rm(options, files); + assertNoError(); + } + + function mv(options, source, destination) { + shell.mv(options, source, destination); + assertNoError(); + } + + function mkdir(options, ...dir) { + shell.mkdir(options, dir); + assertNoError(); + } + + function echo(command) { + return shell.echo(command); + } + + function assertNoError() { + const error = shell.error(); + if (error) { + echo(error); + restore(); + shell.exit(1); } - - function mkdir(options, ...dir) { - shell.mkdir(options, dir); - assertNoError(); + } + + function restore() { + if (fs.existsSync(path(rootPath, '.node_modules'))) { + echo( + "🔧 >>> [Restore] Renaming the root '.node_modules' folder to 'node_modules'..." + ); + mv('-f', path(rootPath, '.node_modules'), path(rootPath, 'node_modules')); + echo( + "👌 >>> [Restore] Renamed the root '.node_modules' folder to 'node_modules'." + ); } - - function echo(command) { - return shell.echo(command); + } + + async function copyFilesToBuildArtifacts() { + echo(`🚢 Detected CI, moving build artifacts...`); + const { platform } = process; + const cwd = path('..', 'build', 'dist'); + const targetFolder = path('..', 'build', 'dist', 'build-artifacts'); + mkdir('-p', targetFolder); + const filesToCopy = []; + const channelFile = getChannelFile(platform); + // Channel file might be an empty string if we're not building a + // nightly or a full release. This can happen when building a package + // locally or a tester build when creating a new PR on GH. + if (!!channelFile && fs.existsSync(join(cwd, channelFile))) { + const channelFilePath = join(cwd, channelFile); + const newChannelFilePath = channelFilePath + ?.replace('latest', 'stable') + ?.replace('beta', 'nightly'); + echo(`🔨 >>> Renaming ${channelFilePath} to ${newChannelFilePath}.`); + cp('-f', channelFilePath, newChannelFilePath); + filesToCopy.push(newChannelFilePath); } - - function assertNoError() { - const error = shell.error(); - if (error) { - echo(error); - restore(); - shell.exit(1); - } + switch (platform) { + case 'linux': { + filesToCopy.push( + ...glob + .sync('**/arduino-ide*.{zip,AppImage}', { cwd }) + .map((p) => join(cwd, p)) + ); + break; + } + case 'win32': { + filesToCopy.push( + ...glob + .sync('**/arduino-ide*.{exe,msi,zip}', { cwd }) + .map((p) => join(cwd, p)) + ); + break; + } + case 'darwin': { + filesToCopy.push( + ...glob + .sync('**/arduino-ide*.{dmg,zip}', { cwd }) + .map((p) => join(cwd, p)) + ); + break; + } + default: { + echo(`Unsupported platform: ${platform}.`); + shell.exit(1); + } } - - function restore() { - if (fs.existsSync(path(rootPath, '.node_modules'))) { - echo('🔧 >>> [Restore] Renaming the root \'.node_modules\' folder to \'node_modules\'...'); - mv('-f', path(rootPath, '.node_modules'), path(rootPath, 'node_modules')); - echo('👌 >>> [Restore] Renamed the root \'.node_modules\' folder to \'node_modules\'.'); - } + if (!filesToCopy.length) { + echo(`Could not collect any build artifacts from ${cwd}.`); + shell.exit(1); } - - async function copyFilesToBuildArtifacts() { - echo(`🚢 Detected CI, moving build artifacts...`); - const { platform } = process; - const cwd = path('..', 'build', 'dist'); - const targetFolder = path('..', 'build', 'dist', 'build-artifacts'); - mkdir('-p', targetFolder); - const filesToCopy = []; - const channelFile = getChannelFile(platform); - // Channel file might be an empty string if we're not building a - // nightly or a full release. This can happen when building a package - // locally or a tester build when creating a new PR on GH. - if (channelFile) { - filesToCopy.push(channelFile) - } - switch (platform) { - case 'linux': { - filesToCopy.push(...glob.sync('**/arduino-ide*.{zip,AppImage}', { cwd }).map(p => join(cwd, p))); - break; - } - case 'win32': { - filesToCopy.push(...glob.sync('**/arduino-ide*.{exe,msi,zip}', { cwd }).map(p => join(cwd, p))); - break; - } - case 'darwin': { - filesToCopy.push(...glob.sync('**/arduino-ide*.{dmg,zip}', { cwd }).map(p => join(cwd, p))); - break; - } - default: { - echo(`Unsupported platform: ${platform}.`); - shell.exit(1); - } - } - if (!filesToCopy.length) { - echo(`Could not collect any build artifacts from ${cwd}.`); - shell.exit(1); - } - for (const fileToCopy of filesToCopy) { - echo(`🚢 >>> Copying ${fileToCopy} to ${targetFolder}.`); - const isZip = await utils.isZip(fileToCopy); - if (isZip) { - await utils.adjustArchiveStructure(fileToCopy, targetFolder); - } else { - cp('-rf', fileToCopy, targetFolder); - } - echo(`👌 >>> Copied ${fileToCopy} to ${targetFolder}.`); - } + for (const fileToCopy of filesToCopy) { + echo(`🚢 >>> Copying ${fileToCopy} to ${targetFolder}.`); + const isZip = await utils.isZip(fileToCopy); + if (isZip) { + await utils.adjustArchiveStructure(fileToCopy, targetFolder); + } else { + cp('-rf', fileToCopy, targetFolder); + } + echo(`👌 >>> Copied ${fileToCopy} to ${targetFolder}.`); } - - /** - * Joins tha path from `__dirname`. - */ - function path(...paths) { - return join(__dirname, ...paths); + } + + /** + * Joins tha path from `__dirname`. + */ + function path(...paths) { + return join(__dirname, ...paths); + } + + function verifyVersions(allDependencies, expectedVersion) { + const versions = new Set(); + for (const dependency of allDependencies) { + versions.add( + require(`../working-copy/${dependency}/package.json`).version + ); } - - function verifyVersions(allDependencies, expectedVersion) { - const versions = new Set(); - for (const dependency of allDependencies) { - versions.add(require(`../working-copy/${dependency}/package.json`).version); - } - if (versions.size !== 1) { - echo(`Mismatching version configuration. All dependencies must have the same version. Versions were: ${JSON.stringify(Array.from(versions), null, 2)}.`); - shell.exit(1); - process.exit(1); - } - if (expectedVersion) { - if (!versions.has(expectedVersion)) { - echo(`Mismatching version configuration. Expected version was: '${expectedVersion}' actual was: '${Array.from(versions)[0]}'.`); - shell.exit(1); - process.exit(1); - } - } + if (versions.size !== 1) { + echo( + `Mismatching version configuration. All dependencies must have the same version. Versions were: ${JSON.stringify( + Array.from(versions), + null, + 2 + )}.` + ); + shell.exit(1); + process.exit(1); } - + if (expectedVersion) { + if (!versions.has(expectedVersion)) { + echo( + `Mismatching version configuration. Expected version was: '${expectedVersion}' actual was: '${ + Array.from(versions)[0] + }'.` + ); + shell.exit(1); + process.exit(1); + } + } + } })(); diff --git a/electron/packager/utils.js b/electron/packager/utils.js index d8e7faf14..d746a98f3 100644 --- a/electron/packager/utils.js +++ b/electron/packager/utils.js @@ -199,9 +199,9 @@ function git(command) { function getChannelFile(platform) { let currentChannel = ''; if (isNightly) { - currentChannel = 'nightly'; + currentChannel = 'beta'; } else if (isRelease) { - currentChannel = 'stable'; + currentChannel = 'latest'; } else { // We're not creating a nightly build nor releasing // a new version, no need for a channel file.