Build on GH Actions. Set up nightly.

Signed-off-by: Akos Kitta <kittaakos@typefox.io>
This commit is contained in:
Akos Kitta 2020-05-14 14:03:17 +02:00
parent d9a866579c
commit 6bb852c613
19 changed files with 1246 additions and 1100 deletions

89
.github/workflows/build.yml vendored Normal file
View File

@ -0,0 +1,89 @@
name: Arduino Pro IDE
on:
push:
branches:
- master
tags:
- 'v[0-9]+.[0-9]+.[0-9]+*'
pull_request:
branches:
- master
schedule:
- cron: '0 3 * * *' # run every day at 3AM (https://docs.github.com/en/actions/reference/events-that-trigger-workflows#scheduled-events-schedule)
env:
IS_NIGHTLY: ${{ github.event_name == 'schedule' || github.head_ref == 'gh-actions' }} # TODO: remove OR once PR is merged.
IS_RELEASE: ${{ startsWith(github.ref, 'refs/tags/v') }}
jobs:
build:
strategy:
matrix:
config:
- os: windows-2016
- os: ubuntu-latest
- os: turin-macmini # self-hosted macOS
runs-on: ${{ matrix.config.os }}
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Install Node.js 10.x
uses: actions/setup-node@v1
with:
node-version: '10.x'
registry-url: 'https://registry.npmjs.org'
- name: Install Python 2.7
uses: actions/setup-python@v2
with:
python-version: '2.7'
- name: Build
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PUPPETEER_SKIP_CHROMIUM_DOWNLOAD: true
run: yarn
- name: Test
run: yarn test
- name: Package
shell: bash
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} # https://github.com/Microsoft/vscode/issues/28434#issuecomment-346199674
PUPPETEER_SKIP_CHROMIUM_DOWNLOAD: true
AC_USERNAME: ${{ secrets.AC_USERNAME }}
AC_PASSWORD: ${{ secrets.AC_PASSWORD }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
run: |
if [ "$RUNNER_OS" == "macOS" ]; then
echo ">>> Detected macOS runner. Updating keychain for the app signing..."
echo "${{ secrets.KEYCHAIN }}" | base64 --decode > ~/Library/Keychains/apple-developer.keychain-db
security list-keychains -s ~/Library/Keychains/apple-developer.keychain-db
security unlock-keychain -p "${{ secrets.KEYCHAIN_PASSWORD }}" ~/Library/Keychains/apple-developer.keychain-db
echo "<<< The keychain has been successfully updated."
fi
yarn --cwd ./electron/packager/
yarn --cwd ./electron/packager/ package
- name: Upload [GitHub Actions]
uses: actions/upload-artifact@v2
with:
name: ${{ runner.os }}
path: electron/build/dist/build-artifacts/
- name: Upload [S3]
if: env.IS_NIGHTLY == 'true'
uses: kittaakos/upload-s3-action@v0.0.1
with:
aws_key_id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws_secret_access_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws_bucket: ${{ secrets.DOWNLOADS_BUCKET }}
source_dir: electron/build/dist/build-artifacts/
destination_dir: arduino-pro-ide/nightly/

2
.vscode/launch.json vendored
View File

@ -13,7 +13,7 @@
{
"type": "node",
"request": "launch",
"name": "Launch Electron Packager",
"name": "Electron Packager",
"program": "${workspaceRoot}/electron/packager/index.js",
"cwd": "${workspaceFolder}/electron/packager"
},

View File

@ -35,7 +35,7 @@
}
}
shell.echo('Generating TS/JS API from:');
shell.echo('>>> Generating TS/JS API from:');
if (shell.exec(`git -C ${repository} rev-parse --abbrev-ref HEAD`).code !== 0) {
shell.exit(1);
}
@ -83,6 +83,6 @@ ${protos.join(' ')}`).code !== 0) {
shell.exit(1);
}
shell.echo('Done.');
shell.echo('<<< Generation was successful.');
})();

View File

@ -1,12 +1,13 @@
import { join } from 'path';
import { homedir } from 'os';
import { injectable } from 'inversify';
import { EnvVariablesServerImpl } from '@theia/core/lib/node/env-variables/env-variables-server';
import { FileUri } from '@theia/core/lib/node/file-uri';
import { EnvVariablesServerImpl } from '@theia/core/lib/node/env-variables/env-variables-server';
import { BackendApplicationConfigProvider } from '@theia/core/lib/node/backend-application-config-provider';
@injectable()
export class ArduinoEnvVariablesServer extends EnvVariablesServerImpl {
protected readonly configDirUri = FileUri.create(join(homedir(), '.arduinoProIDE')).toString();
protected readonly configDirUri = FileUri.create(join(homedir(), BackendApplicationConfigProvider.get().configDirName)).toString();
}

View File

@ -1,81 +0,0 @@
trigger:
batch: true
branches:
include:
- master
pr:
- master
jobs:
- job: Build
strategy:
matrix:
linux:
imageName: 'ubuntu-16.04'
mac:
imageName: 'macos-10.14'
windows:
imageName: 'vs2017-win2016'
pool:
vmImage: $(imageName)
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '2.7'
architecture: 'x64'
displayName: '[Config] Use - Python 2.7'
- task: NodeTool@0
inputs:
versionSpec: '10.x'
displayName: '[Config] Use - Node.js 10.x'
- script: yarn
env:
GITHUB_TOKEN: $(Personal.GitHub.Token)
THEIA_ELECTRON_SKIP_REPLACE_FFMPEG: 1
displayName: Build
- script: yarn test
displayName: Test
- bash: |
./electron/packager/conf-node-gyp.sh
yarn --cwd ./electron/packager/
yarn --cwd ./electron/packager/ package
env:
GITHUB_TOKEN: $(Personal.GitHub.Token)
RELEASE_TAG: $(Release.Tag)
condition: or(in(variables['Agent.OS'], 'Windows_NT'), in(variables['Build.Reason'], 'Manual', 'Schedule'))
displayName: Package
- task: PublishBuildArtifacts@1
inputs:
pathtoPublish: electron/build/dist/build-artifacts
artifactName: 'Arduino Pro IDE - Applications'
condition: or(in(variables['Agent.OS'], 'Windows_NT'), in(variables['Build.Reason'], 'Manual', 'Schedule'))
displayName: Publish
- job: Release
pool:
vmImage: ubuntu-16.04
dependsOn:
- Build
condition: and(succeeded(), and(in(variables['Build.Reason'], 'Manual', 'Schedule'), startsWith(variables['Release.Tag'], 'v')))
steps:
- task: DownloadBuildArtifacts@0
displayName: Download
inputs:
artifactName: 'Arduino Pro IDE - Applications'
downloadPath: 'gh-release'
- task: GithubRelease@0
inputs:
gitHubConnection: typefox-service-account1
repositoryName: bcmi-labs/arduino-editor
assets: |
gh-release/Arduino Pro IDE - Applications/*.zip
gh-release/Arduino Pro IDE - Applications/*.dmg
gh-release/Arduino Pro IDE - Applications/*.AppImage
target: $(Build.SourceVersion)
action: Edit
tagSource: auto
tag: $(Release.Tag)
assetUploadMode: delete
isDraft: true
addChangeLog: false
displayName: Release

View File

@ -44,6 +44,11 @@
}
}
},
"backend": {
"config": {
"configDirName": ".arduinoProIDE"
}
},
"generator": {
"config": {
"preloadTemplate": "<div class='theia-preload' style='background-color: rgb(237, 241, 242);'></div>"

View File

@ -48,3 +48,4 @@ One has to manually publish the GitHub release.
- Select `Publish release`.
- ✨

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
<true/>
</dict>
</plist>

View File

@ -1,13 +0,0 @@
const os = require('os');
const path = require('path');
// To be able to propagate the `process.versions.electron` to the backend main, so that we can load natives correctly.
process.env.THEIA_ELECTRON_VERSION = process.versions.electron;
process.env.THEIA_DEFAULT_PLUGINS = `local-dir:${path.resolve(__dirname, '..', 'plugins')}`;
process.env.THEIA_PLUGINS = [
process.env.THEIA_PLUGINS,
`local-dir:${path.resolve(os.homedir(), '.arduinoProIDE', 'plugins')}`
].filter(Boolean).join(',');
require('../src-gen/frontend/electron-main.js');

View File

@ -0,0 +1,24 @@
const isCI = require('is-ci');
const { notarize } = require('electron-notarize');
exports.default = async function notarizing(context) {
if (!isCI) {
console.log('Skipping notarization: not on CI.');
return;
}
const { electronPlatformName, appOutDir } = context;
if (electronPlatformName !== 'darwin') {
return;
}
const appName = context.packager.appInfo.productFilename;
const appBundleId = context.packager.config.appId;
console.log(`>>> Notarizing ${appBundleId} at ${appOutDir}/${appName}.app...`);
return await notarize({
appBundleId,
appPath: `${appOutDir}/${appName}.app`,
appleId: process.env.AC_USERNAME,
appleIdPassword: process.env.AC_PASSWORD,
});
};

View File

@ -1,57 +0,0 @@
//@ts-check
// Patches the `src-gen/backend/main.js` so that the forked backend process has the `process.versions.electron` in the bundled electron app.
// https://github.com/eclipse-theia/theia/issues/7358#issue-583306096
const args = process.argv.slice(2);
if (!args.length) {
console.error(`Expected an argument pointing to the app folder. An app folder is where you have the package.json and src-gen folder.`);
process.exit(1);
}
if (args.length > 1) {
console.error(`Expected exactly one argument pointing to the app folder. Got multiple instead: ${JSON.stringify(args)}`);
process.exit(1);
}
const arg = args.shift();
if (!arg) {
console.error('App path was not specified.');
process.exit(1);
}
const fs = require('fs');
const path = require('path');
const appPath = path.resolve((path.isAbsolute(arg) ? path.join(process.cwd(), arg) : arg));
if (!fs.existsSync(appPath)) {
console.error(`${appPath} does not exist.`);
process.exit(1);
}
if (!fs.lstatSync(appPath).isDirectory()) {
console.error(`${appPath} is not a directory.`);
process.exit(1);
}
const patched = path.join(appPath, 'src-gen', 'backend', 'original-main.js');
if (fs.existsSync(patched)) {
console.error(`Already patched. ${patched} already exists.`);
process.exit(1);
}
const toPatch = path.join(appPath, 'src-gen', 'backend', 'main.js');
if (fs.existsSync(patched)) {
console.error(`Cannot patch. ${toPatch} does not exist.`);
process.exit(1);
}
console.log(`⏱️ >>> Patching ${toPatch}...`);
const originalContent = fs.readFileSync(toPatch, { encoding: 'utf8' });
const patchedContent = `if (typeof process.versions.electron === 'undefined' && typeof process.env.THEIA_ELECTRON_VERSION === 'string') {
process.versions.electron = process.env.THEIA_ELECTRON_VERSION;
}
require('./original-main');
`
fs.writeFileSync(patched, originalContent);
fs.writeFileSync(toPatch, patchedContent);
console.log(`👌 <<< Patched ${toPatch}. Original 'main.js' is now at ${patched}.`);

View File

@ -1,25 +1,23 @@
{
"name": "arduino-pro-ide",
"description": "Arduino Pro IDE",
"main": "scripts/arduino-pro-ide-electron-main.js",
"main": "src-gen/frontend/electron-main.js",
"author": "Arduino SA",
"dependencies": {
"arduino-ide-extension": "file:../working-copy/arduino-ide-extension",
"arduino-debugger-extension": "file:../working-copy/arduino-debugger-extension"
},
"resolutions": {
"**/fs-extra": "^4.0.3"
},
"devDependencies": {
"@theia/cli": "next",
"electron-builder": "^22.4.1"
"cross-env": "^7.0.2",
"electron-builder": "^22.4.1",
"electron-notarize": "^0.3.0",
"is-ci": "^2.0.0",
"shelljs": "^0.8.3"
},
"scripts": {
"build": "yarn download:plugins && theia build --mode development && yarn patch:main",
"build:release": "yarn download:plugins && theia build --mode production && yarn patch:main",
"package": "electron-builder --publish=never",
"download:plugins": "theia download:plugins",
"patch:main": "node ./scripts/patch-backend-main ."
"build": "yarn download:plugins && theia build --mode development",
"build:publish": "yarn download:plugins && theia build --mode production",
"package": "cross-env DEBUG=* && electron-builder --publish=never",
"package:publish": "cross-env DEBUG=* && electron-builder --publish=always",
"download:plugins": "theia download:plugins"
},
"engines": {
"node": ">=10.11.0 <12"
@ -35,8 +33,15 @@
"target": "electron",
"frontend": {
"config": {
"applicationName": "Arduino Pro IDE",
"disallowReloadKeybinding": true
}
},
"backend": {
"config": {
"singleInstance": true,
"configDirName": ".arduinoProIDE"
}
}
},
"build": {
@ -49,7 +54,6 @@
"files": [
"src-gen",
"lib",
"scripts",
"!node_modules/**/*.{ts,map}",
"!node_modules/**/*.spec.js",
"!node_modules/@theia/**/test/*",
@ -68,29 +72,23 @@
"win": {
"target": [
"zip"
],
"artifactName": "${productName}-${env.ARDUINO_VERSION}-${os}.${ext}"
]
},
"mac": {
"target": [
"dmg"
],
"artifactName": "${productName}-${env.ARDUINO_VERSION}-${os}.${ext}",
"darkModeSupport": true
"darkModeSupport": true,
"hardenedRuntime": true,
"gatekeeperAssess": false,
"entitlements": "resources/entitlements.mac.plist",
"entitlementsInherit": "resources/entitlements.mac.plist"
},
"linux": {
"target": [
{
"target": "zip"
},
{
"target": "AppImage",
"arch": "armv7l"
}
],
"category": "Development",
"icon": "resources/icons",
"artifactName": "${productName}-${env.ARDUINO_VERSION}-${os}-${arch}.${ext}"
"icon": "resources/icons"
},
"dmg": {
"icon": "resources/icon.icns",
@ -108,11 +106,19 @@
"type": "file"
}
]
}
},
"afterSign": "scripts/notarize.js",
"publish": [
{
"provider": "s3",
"bucket": "arduino-downloads-prod-beagle",
"path": "arduino-pro-ide/nightly"
}
]
},
"theiaPluginsDir": "plugins",
"theiaPlugins": {
"vscode-yaml": "https://open-vsx.org/api/redhat/vscode-yaml/0.7.2/file/redhat.vscode-yaml-0.7.2.vsix",
"vscode-builtin-cpp": "http://open-vsx.org/api/vscode/cpp/1.39.1/file/vscode.cpp-1.39.1.vsix"
"vscode-builtin-cpp": "http://open-vsx.org/api/vscode/cpp/1.44.2/file/vscode.cpp-1.44.2.vsix",
"vscode-yaml": "https://open-vsx.org/api/redhat/vscode-yaml/0.7.2/file/redhat.vscode-yaml-0.7.2.vsix"
}
}

122
electron/packager/config.js Normal file
View File

@ -0,0 +1,122 @@
//@ts-check
const fs = require('fs');
const path = require('path');
const semver = require('semver');
const merge = require('deepmerge');
const dateFormat = require('dateformat');
const { isNightly, isRelease, git } = require('./utils');
function artifactName() {
const { platform, arch } = process;
const id = (() => {
if (isRelease) {
return 'latest';
} else if (isNightly) {
return `nightly-${timestamp()}`
} else {
return 'snapshot';
}
})();
const name = 'arduino-pro-ide';
switch (platform) {
case 'win32': {
if (arch === 'x64') {
return `${name}_${id}_Windows_64bit.\$\{ext}`;
}
throw new Error(`Unsupported platform, arch: ${platform}, ${arch}`);
}
case 'darwin': {
return `${name}_${id}_macOS_64bit.\$\{ext}`;
}
case 'linux': {
switch (arch) {
case 'arm': {
return `${name}_${id}_Linux_ARMv7.\$\{ext}`;
}
case 'arm64': {
return `${name}_${id}_Linux_ARM64.\$\{ext}`;
}
case 'x64': {
return `${name}_${id}_Linux_64bit.\$\{ext}`;
}
default: {
throw new Error(`Unsupported platform, arch: ${platform}, ${arch}`);
}
}
}
default: throw new Error(`Unsupported platform, arch: ${platform}, ${arch}`);
}
}
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}.`);
}
}
function getVersion() {
const repositoryRootPath = git('rev-parse --show-toplevel');
let version = JSON.parse(fs.readFileSync(path.join(repositoryRootPath, 'package.json'), { encoding: 'utf8' })).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.${timestamp()}`;
} else {
version = `${version}-snapshot.${currentCommitish()}`;
}
if (!semver.valid(version)) {
throw new Error(`Invalid patched version: '${version}'.`);
}
} else {
version = `v${version}`;
}
return version;
}
function timestamp() {
return dateFormat(new Date(), 'yyyymmdd');
}
function currentCommitish() {
return git('rev-parse --short HEAD');
}
// function currentBranch() {
// return git('rev-parse --abbrev-ref HEAD');
// }
function generateTemplate() {
// do `export PUBLISH=true yarn package` if you want to mimic CI build locally.
// const electronPublish = release || (isCI && currentBranch() === 'master') || process.env.PUBLISH === 'true';
const version = getVersion();
const productName = 'Arduino Pro IDE';
const name = 'arduino-pro-ide';
const customizations = {
name,
description: productName,
version,
build: {
productName,
appId: 'arduino.ProIDE',
[electronPlatform()]: {
artifactName: artifactName()
}
}
};
const template = require('../build/template-package.json');
return merge(template, customizations);
}
module.exports = { generateTemplate };

View File

@ -9,11 +9,14 @@
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
const template = require('./config').generateTemplate();
const utils = require('./utils');
const merge = require('deepmerge');
const { version, release } = utils.versionInfo();
const { isRelease, isElectronPublish } = utils;
const { version } = template;
const { productName } = template.build;
echo(`📦 Building ${release ? 'release ' : ''}version '${version}'...`);
echo(`📦 Building ${isRelease ? 'release ' : ''}version '${version}'...`);
const workingCopy = 'working-copy';
@ -40,17 +43,47 @@
// Clean up the `./electron/build` folder.
shell.exec(`git -C ${path('..', 'build')} clean -ffxdq`, { async: false });
const extensions = [
'arduino-ide-extension',
'arduino-debugger-extension',
];
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 ['arduino-ide-extension', 'arduino-debugger-extension', 'electron-app', 'yarn.lock', 'package.json', 'lerna.json']) {
for (const name of [...allDependencies, 'yarn.lock', 'package.json', 'lerna.json']) {
cp('-rf', path(rootPath, name), path('..', workingCopy));
}
//---------------------------------------------+
// No need to build the `browser-app` example. |
//---------------------------------------------+
//----------------------------------------------+
// 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;
@ -68,7 +101,7 @@
//-------------------------------------------------------------------------------------------------+
// 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 Arduino Pro IDE extensions');
exec(`yarn --network-timeout 1000000 --cwd ${path('..', workingCopy)}`, `Building 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`.
@ -77,32 +110,45 @@
//-------------------------------------------------------------------------------------------------------------+
// Change the regular NPM dependencies to `local-paths`, so that we can build them without any NPM registries. |
//-------------------------------------------------------------------------------------------------------------+
// @ts-ignore
pkg = require('../working-copy/arduino-debugger-extension/package.json');
pkg.dependencies['arduino-ide-extension'] = 'file:../arduino-ide-extension';
fs.writeFileSync(path('..', workingCopy, 'arduino-debugger-extension', 'package.json'), JSON.stringify(pkg, null, 2));
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');
// @ts-ignore
const template = require('../build/template-package.json');
template.build.files = [...template.build.files, ...unusedDependencies.map(name => `!node_modules/${name}`)];
pkg.dependencies = { ...pkg.dependencies, ...template.dependencies };
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 || {}));
fs.writeFileSync(path('..', 'build', 'package.json'), JSON.stringify({
const content = {
...pkg,
...template,
theia,
// @ts-ignore
dependencies: pkg.dependencies,
devDependencies: pkg.devDependencies
}, null, 2));
};
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 Arduino Pro IDE application is:
echo(`📜 Effective 'package.json' for the ${productName} application is:
-----------------------
${fs.readFileSync(path('..', 'build', 'package.json')).toString()}
-----------------------
@ -123,7 +169,7 @@ ${fs.readFileSync(path('..', 'build', 'package.json')).toString()}
// 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${release ? ':release' : ''}`, 'Building the Arduino Pro IDE application');
exec(`yarn --network-timeout 1000000 --cwd ${path('..', 'build')} build${isElectronPublish ? ':publish' : ''}`, `Building the ${productName} application`);
//------------------------------------------------------------------------------+
// Create a throw away dotenv file which we use to feed the builder with input. |
@ -139,7 +185,7 @@ ${fs.readFileSync(path('..', 'build', 'package.json')).toString()}
//-----------------------------------+
// Package the electron application. |
//-----------------------------------+
exec(`yarn --network-timeout 1000000 --cwd ${path('..', 'build')} package`, `Packaging your Arduino Pro IDE 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` |
@ -224,15 +270,15 @@ ${fs.readFileSync(path('..', 'build', 'package.json')).toString()}
const filesToCopy = [];
switch (platform) {
case 'linux': {
filesToCopy.push(...glob.sync('**/Arduino Pro IDE*.{zip,AppImage}', { cwd }).map(p => join(cwd, p)));
filesToCopy.push(...glob.sync('**/arduino-pro-ide*.{zip,AppImage}', { cwd }).map(p => join(cwd, p)));
break;
}
case 'win32': {
filesToCopy.push(...glob.sync('**/Arduino Pro IDE*.zip', { cwd }).map(p => join(cwd, p)));
filesToCopy.push(...glob.sync('**/arduino-pro-ide*.zip', { cwd }).map(p => join(cwd, p)));
break;
}
case 'darwin': {
filesToCopy.push(...glob.sync('**/Arduino Pro IDE*.dmg', { cwd }).map(p => join(cwd, p)));
filesToCopy.push(...glob.sync('**/arduino-pro-ide*.{dmg,zip}', { cwd }).map(p => join(cwd, p)));
break;
}
default: {
@ -263,4 +309,23 @@ ${fs.readFileSync(path('..', 'build', 'package.json')).toString()}
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);
}
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);
}
}
}
})();

View File

@ -17,12 +17,14 @@
"@types/temp": "^0.8.32",
"7zip-min": "^1.1.1",
"chai": "^4.2.0",
"dateformat": "^3.0.3",
"deepmerge": "^4.2.2",
"depcheck": "^0.9.2",
"file-type": "^14.1.4",
"glob": "^7.1.6",
"is-ci": "^2.0.0",
"mocha": "^7.1.1",
"semver": "^7.3.2",
"sinon": "^9.0.1",
"shelljs": "^0.8.3",
"temp": "^0.9.1",

View File

@ -1,70 +1,15 @@
//@ts-check
const fs = require('fs');
const path = require('path');
const temp = require('temp');
const zip = require('7zip-min');
const temp = require('temp');
const path = require('path');
const isCI = require('is-ci');
const shell = require('shelljs');
const semver = require('semver');
const depcheck = require('depcheck');
const fromFile = require('file-type').fromFile;
/**
* Returns with the version info for the artifact.
* If the `RELEASE_TAG` environment variable is set, we us that.
* Falls back to the commit SHA if the `RELEASE_TAG` is the `$(Release.Tag)` string.
* Otherwise, we concatenate the version of the extracted from `theia-app/electron-app/package.json`
* and append the short commit SHA.
*/
function versionInfo() {
if (typeof process.env.RELEASE_TAG === 'undefined' || !process.env.RELEASE_TAG || /* Azure -> */ process.env.RELEASE_TAG === '$(Release.Tag)') {
return {
version: `${targetVersion()}-${currentCommitish()}`,
release: false
}
} else {
return {
version: process.env.RELEASE_TAG,
release: true
}
}
}
/**
* Returns with the absolute path of the `theia-app/electron-app/`.
*/
function arduinoExtensionPath() {
// TODO: be smarter and locate the extension with Git: `git rev-parse --show-toplevel`.
return path.join(__dirname, '..', '..', 'arduino-ide-extension');
}
/**
* The version extracted from the `package.json` of the `arduino-ide-extension`. Falls back to `x.x.x`.
*/
function targetVersion() {
return JSON.parse(fs.readFileSync(path.join(arduinoExtensionPath(), 'package.json'), { encoding: 'utf8' })).version || 'x.x.x';
}
/**
* Returns with the trimmed result of the `git rev-parse --short HEAD` as the current commitish if `git` is on the `PATH`.
* Otherwise, it returns with `DEV_BUILD`.
*/
function currentCommitish() {
try {
const gitPath = shell.which('git');
const error = shell.error();
if (error) {
throw new Error(error);
}
const { stderr, stdout } = shell.exec(`"${gitPath}" rev-parse --short HEAD`, { silent: true });
if (stderr) {
throw new Error(stderr.toString().trim());
}
return stdout.toString().trim();
} catch (e) {
return 'DEV_BUILD';
}
}
/**
* Resolves to an array of `npm` package names that are declared in the `package.json` but **not** used by the project.
*/
@ -204,4 +149,25 @@ async function isZip(pathToFile) {
return type && type.ext === 'zip';
}
module.exports = { versionInfo, collectUnusedDependencies, adjustArchiveStructure, isZip, unpack };
const isElectronPublish = false; // TODO: support auto-updates
const isNightly = process.env.IS_NIGHTLY === 'true';
const isRelease = process.env.IS_RELEASE === 'true';
function git(command) {
try {
const gitPath = shell.which('git');
const error = shell.error();
if (error) {
throw new Error(error);
}
const { stderr, stdout } = shell.exec(`"${gitPath}" ${command}`, { silent: true });
if (stderr) {
throw new Error(stderr.toString().trim());
}
return stdout.toString().trim();
} catch (e) {
throw e;
}
}
module.exports = { collectUnusedDependencies, adjustArchiveStructure, isZip, unpack, isNightly, isRelease, isElectronPublish, git };

View File

@ -437,6 +437,11 @@ cross-spawn@^6.0.0:
shebang-command "^1.2.0"
which "^1.2.9"
dateformat@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae"
integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==
de-indent@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d"
@ -1306,6 +1311,11 @@ semver@^5.5.0, semver@^5.7.0:
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
semver@^7.3.2:
version "7.3.2"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938"
integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==
set-blocking@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"

View File

@ -14,7 +14,7 @@
"typescript": "^3.9.2"
},
"scripts": {
"prepare": "lerna run prepare && yarn test && yarn download:plugins",
"prepare": "lerna run prepare && yarn download:plugins",
"rebuild:browser": "theia rebuild:browser",
"rebuild:electron": "theia rebuild:electron --modules \"@theia/node-pty\" nsfw native-keymap find-git-repositories grpc",
"start": "yarn --cwd ./browser-app start",
@ -30,7 +30,7 @@
],
"theiaPluginsDir": "plugins",
"theiaPlugins": {
"vscode-yaml": "https://open-vsx.org/api/redhat/vscode-yaml/0.7.2/file/redhat.vscode-yaml-0.7.2.vsix",
"vscode-builtin-cpp": "http://open-vsx.org/api/vscode/cpp/1.39.1/file/vscode.cpp-1.39.1.vsix"
"vscode-builtin-cpp": "http://open-vsx.org/api/vscode/cpp/1.44.2/file/vscode.cpp-1.44.2.vsix",
"vscode-yaml": "https://open-vsx.org/api/redhat/vscode-yaml/0.7.2/file/redhat.vscode-yaml-0.7.2.vsix"
}
}

1650
yarn.lock

File diff suppressed because it is too large Load Diff