build: determine electron version from tags not files (#36106)

* build: determine electron version from tags not files

* build: make electron_version dependent on packed-refs and git HEAD

* build: do not delete electron/.git

* build: do not revert a commit we didn't make

* build: gen version file instead of just writing it

* build: update cache and ninja targets

* build: copy resource.h to generated electron.rc

* build: electron_win32_resources should be public deps

* build: also copy the icon
This commit is contained in:
Samuel Attard 2022-10-24 23:44:43 -07:00 committed by GitHub
parent ad289d120f
commit 7ca2bb5f9c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 145 additions and 260 deletions

View file

@ -455,7 +455,7 @@ step-delete-git-directories: &step-delete-git-directories
command: | command: |
if [ "`uname`" == "Darwin" ]; then if [ "`uname`" == "Darwin" ]; then
cd src cd src
( find . -type d -name ".git" -not -path "./third_party/angle/*" -not -path "./third_party/dawn/*" ) | xargs rm -rf ( find . -type d -name ".git" -not -path "./third_party/angle/*" -not -path "./third_party/dawn/*" -not -path "./electron/*" ) | xargs rm -rf
fi fi
# On macOS the yarn install command during gclient sync was run on a linux # On macOS the yarn install command during gclient sync was run on a linux
@ -814,7 +814,7 @@ step-maybe-zip-symbols: &step-maybe-zip-symbols
cd src cd src
export BUILD_PATH="$PWD/out/Default" export BUILD_PATH="$PWD/out/Default"
ninja -C out/Default electron:licenses ninja -C out/Default electron:licenses
ninja -C out/Default electron:electron_version ninja -C out/Default electron:electron_version_file
DELETE_DSYMS_AFTER_ZIP=1 electron/script/zip-symbols.py -b $BUILD_PATH DELETE_DSYMS_AFTER_ZIP=1 electron/script/zip-symbols.py -b $BUILD_PATH
step-maybe-cross-arch-snapshot: &step-maybe-cross-arch-snapshot step-maybe-cross-arch-snapshot: &step-maybe-cross-arch-snapshot
@ -874,12 +874,12 @@ step-touch-sync-done: &step-touch-sync-done
step-maybe-restore-src-cache: &step-maybe-restore-src-cache step-maybe-restore-src-cache: &step-maybe-restore-src-cache
restore_cache: restore_cache:
keys: keys:
- v14-src-cache-{{ checksum "src/electron/.depshash" }} - v15-src-cache-{{ checksum "src/electron/.depshash" }}
name: Restoring src cache name: Restoring src cache
step-maybe-restore-src-cache-marker: &step-maybe-restore-src-cache-marker step-maybe-restore-src-cache-marker: &step-maybe-restore-src-cache-marker
restore_cache: restore_cache:
keys: keys:
- v14-src-cache-marker-{{ checksum "src/electron/.depshash" }} - v15-src-cache-marker-{{ checksum "src/electron/.depshash" }}
name: Restoring src cache marker name: Restoring src cache marker
# Restore exact or closest git cache based on the hash of DEPS and .circle-sync-done # Restore exact or closest git cache based on the hash of DEPS and .circle-sync-done
@ -954,13 +954,14 @@ step-minimize-workspace-size-from-checkout: &step-minimize-workspace-size-from-c
rm -rf third_party/electron_node/deps/openssl rm -rf third_party/electron_node/deps/openssl
rm -rf third_party/electron_node/deps/v8 rm -rf third_party/electron_node/deps/v8
rm -rf chrome/test/data/xr/webvr_info rm -rf chrome/test/data/xr/webvr_info
rm -rf src/third_party/angle/third_party/VK-GL-CTS/src
# Save the src cache based on the deps hash # Save the src cache based on the deps hash
step-save-src-cache: &step-save-src-cache step-save-src-cache: &step-save-src-cache
save_cache: save_cache:
paths: paths:
- /var/portal - /var/portal
key: v14-src-cache-{{ checksum "/var/portal/src/electron/.depshash" }} key: v15-src-cache-{{ checksum "/var/portal/src/electron/.depshash" }}
name: Persisting src cache name: Persisting src cache
step-make-src-cache-marker: &step-make-src-cache-marker step-make-src-cache-marker: &step-make-src-cache-marker
run: run:
@ -970,7 +971,7 @@ step-save-src-cache-marker: &step-save-src-cache-marker
save_cache: save_cache:
paths: paths:
- .src-cache-marker - .src-cache-marker
key: v14-src-cache-marker-{{ checksum "/var/portal/src/electron/.depshash" }} key: v15-src-cache-marker-{{ checksum "/var/portal/src/electron/.depshash" }}
step-maybe-early-exit-no-doc-change: &step-maybe-early-exit-no-doc-change step-maybe-early-exit-no-doc-change: &step-maybe-early-exit-no-doc-change
run: run:

View file

@ -107,6 +107,13 @@ branding = read_file("shell/app/BRANDING.json", "json")
electron_project_name = branding.project_name electron_project_name = branding.project_name
electron_product_name = branding.product_name electron_product_name = branding.product_name
electron_mac_bundle_id = branding.mac_bundle_id electron_mac_bundle_id = branding.mac_bundle_id
electron_version = exec_script("script/print-version.py",
[],
"trim string",
[
".git/packed-refs",
".git/HEAD",
])
if (is_mas_build) { if (is_mas_build) {
assert(is_mac, assert(is_mac,
@ -313,12 +320,9 @@ npm_action("electron_version_args") {
outputs = [ "$target_gen_dir/electron_version.args" ] outputs = [ "$target_gen_dir/electron_version.args" ]
args = rebase_path(outputs) args = rebase_path(outputs) + [ "$electron_version" ]
inputs = [ inputs = [ "script/generate-version-json.js" ]
"ELECTRON_VERSION",
"script/generate-version-json.js",
]
} }
templated_file("electron_version_header") { templated_file("electron_version_header") {
@ -330,6 +334,39 @@ templated_file("electron_version_header") {
args_files = get_target_outputs(":electron_version_args") args_files = get_target_outputs(":electron_version_args")
} }
templated_file("electron_win_rc") {
deps = [ ":electron_version_args" ]
template = "build/templates/electron_rc.tmpl"
output = "$target_gen_dir/win-resources/electron.rc"
args_files = get_target_outputs(":electron_version_args")
}
copy("electron_win_resource_files") {
sources = [
"shell/browser/resources/win/electron.ico",
"shell/browser/resources/win/resource.h",
]
outputs = [ "$target_gen_dir/win-resources/{{source_file_part}}" ]
}
templated_file("electron_version_file") {
deps = [ ":electron_version_args" ]
template = "build/templates/version_string.tmpl"
output = "$root_build_dir/version"
args_files = get_target_outputs(":electron_version_args")
}
group("electron_win32_resources") {
public_deps = [
":electron_win_rc",
":electron_win_resource_files",
]
}
action("electron_fuses") { action("electron_fuses") {
script = "build/fuses/build.py" script = "build/fuses/build.py"
@ -763,7 +800,6 @@ if (is_mac) {
electron_helper_name = "$electron_product_name Helper" electron_helper_name = "$electron_product_name Helper"
electron_login_helper_name = "$electron_product_name Login Helper" electron_login_helper_name = "$electron_product_name Login Helper"
electron_framework_version = "A" electron_framework_version = "A"
electron_version = read_file("ELECTRON_VERSION", "trim string")
mac_xib_bundle_data("electron_xibs") { mac_xib_bundle_data("electron_xibs") {
sources = [ "shell/common/resources/mac/MainMenu.xib" ] sources = [ "shell/common/resources/mac/MainMenu.xib" ]
@ -1204,6 +1240,7 @@ if (is_mac) {
":default_app_asar", ":default_app_asar",
":electron_app_manifest", ":electron_app_manifest",
":electron_lib", ":electron_lib",
":electron_win32_resources",
":packed_resources", ":packed_resources",
"//components/crash/core/app", "//components/crash/core/app",
"//content:sandbox_helper_win", "//content:sandbox_helper_win",
@ -1237,8 +1274,7 @@ if (is_mac) {
if (is_win) { if (is_win) {
sources += [ sources += [
# TODO: we should be generating our .rc files more like how chrome does "$target_gen_dir/win-resources/electron.rc",
"shell/browser/resources/win/electron.rc",
"shell/browser/resources/win/resource.h", "shell/browser/resources/win/resource.h",
] ]
@ -1420,15 +1456,10 @@ group("licenses") {
] ]
} }
copy("electron_version") {
sources = [ "ELECTRON_VERSION" ]
outputs = [ "$root_build_dir/version" ]
}
dist_zip("electron_dist_zip") { dist_zip("electron_dist_zip") {
data_deps = [ data_deps = [
":electron_app", ":electron_app",
":electron_version", ":electron_version_file",
":licenses", ":licenses",
] ]
if (is_linux) { if (is_linux) {

View file

@ -1 +0,0 @@
23.0.0-nightly.20221024

View file

@ -50,8 +50,8 @@ END
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 23,0,0,20221024 FILEVERSION $major,$minor,$patch,$prerelease_number
PRODUCTVERSION 23,0,0,20221024 PRODUCTVERSION $major,$minor,$patch,$prerelease_number
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -68,12 +68,12 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "GitHub, Inc." VALUE "CompanyName", "GitHub, Inc."
VALUE "FileDescription", "Electron" VALUE "FileDescription", "Electron"
VALUE "FileVersion", "23.0.0" VALUE "FileVersion", "$major.$minor.$patch"
VALUE "InternalName", "electron.exe" VALUE "InternalName", "electron.exe"
VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved." VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved."
VALUE "OriginalFilename", "electron.exe" VALUE "OriginalFilename", "electron.exe"
VALUE "ProductName", "Electron" VALUE "ProductName", "Electron"
VALUE "ProductVersion", "23.0.0" VALUE "ProductVersion", "$major.$minor.$patch"
VALUE "SquirrelAwareVersion", "1" VALUE "SquirrelAwareVersion", "1"
END END
END END

View file

@ -0,0 +1 @@
$full_version

View file

@ -1,6 +1,6 @@
{ {
"name": "electron", "name": "electron",
"version": "23.0.0-nightly.20221024", "version": "0.0.0-development",
"repository": "https://github.com/electron/electron", "repository": "https://github.com/electron/electron",
"description": "Build cross platform desktop apps with JavaScript, HTML, and CSS", "description": "Build cross platform desktop apps with JavaScript, HTML, and CSS",
"devDependencies": { "devDependencies": {

View file

@ -120,3 +120,4 @@ feat_ensure_mas_builds_of_the_same_application_can_use_safestorage.patch
fix_on-screen-keyboard_hides_on_input_blur_in_webview.patch fix_on-screen-keyboard_hides_on_input_blur_in_webview.patch
preconnect_manager.patch preconnect_manager.patch
fix_remove_caption-removing_style_call.patch fix_remove_caption-removing_style_call.patch
build_allow_electron_to_use_exec_script.patch

View file

@ -0,0 +1,18 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Samuel Attard <sattard@salesforce.com>
Date: Fri, 21 Oct 2022 16:29:06 -0700
Subject: build: allow electron to use exec_script
This is similar to the //build usecase so we're OK adding ourselves here
diff --git a/.gn b/.gn
index 55f5ee19f13e49dfd0aa2300d980d813474c95ef..483e0f0598bfed76b4a4283be3cfa1fdb9eafe5a 100644
--- a/.gn
+++ b/.gn
@@ -169,4 +169,6 @@ exec_script_whitelist =
"//tools/grit/grit_rule.gni",
"//tools/gritsettings/BUILD.gn",
+
+ "//electron/BUILD.gn"
]

View file

@ -3,8 +3,7 @@ const path = require('path');
const semver = require('semver'); const semver = require('semver');
const outputPath = process.argv[2]; const outputPath = process.argv[2];
const currentVersion = process.argv[3];
const currentVersion = fs.readFileSync(path.resolve(__dirname, '../ELECTRON_VERSION'), 'utf8').trim();
const parsed = semver.parse(currentVersion); const parsed = semver.parse(currentVersion);
@ -20,9 +19,11 @@ const {
} = parsed; } = parsed;
fs.writeFileSync(outputPath, JSON.stringify({ fs.writeFileSync(outputPath, JSON.stringify({
full_version: currentVersion,
major, major,
minor, minor,
patch, patch,
prerelease, prerelease,
prerelease_number: prerelease ? parsed.prerelease[parsed.prerelease.length - 1] : '0',
has_prerelease: prerelease === '' ? 0 : 1 has_prerelease: prerelease === '' ? 0 : 1
}, null, 2)); }, null, 2));

20
script/lib/get-version.js Normal file
View file

@ -0,0 +1,20 @@
const { spawnSync } = require('child_process');
const rootPackageJson = require('../../package.json');
module.exports.getElectronVersion = () => {
// Find the nearest tag to the current HEAD
// This is equivilant to our old logic of "use a value in package.json" for the following reasons
//
// 1. Whenever we updated the package.json we ALSO pushed a tag with the same version
// 2. Whenever we _reverted_ a bump all we actually did was push a commit that deleted the tag and changed the version number back
//
// The only difference in the "git describe" technique is that technically a commit can "change" it's version
// number if a tag is created / removed retroactively. i.e. the first time a commit is pushed it will be 1.2.3
// and after the tag is made rebuilding the same commit will result in it being 1.2.4
const output = spawnSync('git', ['describe', '--tags', '--abbrev=0']);
if (output.status !== 0) {
console.error(output.stderr);
throw new Error('Failed to get current electron version');
}
return output.stdout.toString().trim();
};

View file

@ -15,7 +15,9 @@ except ImportError:
from urllib2 import urlopen from urllib2 import urlopen
import zipfile import zipfile
from lib.config import is_verbose_mode # from lib.config import is_verbose_mode
def is_verbose_mode():
return False
ELECTRON_DIR = os.path.abspath( ELECTRON_DIR = os.path.abspath(
os.path.dirname(os.path.dirname(os.path.dirname(__file__))) os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
@ -149,11 +151,17 @@ def get_electron_branding():
with open(branding_file_path) as f: with open(branding_file_path) as f:
return json.load(f) return json.load(f)
cached_electron_version = None
def get_electron_version(): def get_electron_version():
SOURCE_ROOT = os.path.abspath(os.path.join(__file__, '..', '..', '..')) global cached_electron_version
version_file = os.path.join(SOURCE_ROOT, 'ELECTRON_VERSION') if cached_electron_version is None:
with open(version_file) as f: cached_electron_version = str.strip(execute([
return 'v' + f.read().strip() 'node',
'-p',
'require("./script/lib/get-version").getElectronVersion()'
], cwd=ELECTRON_DIR).decode())
return cached_electron_version
def store_artifact(prefix, key_prefix, files): def store_artifact(prefix, key_prefix, files):
# Azure Storage # Azure Storage

3
script/print-version.py Normal file
View file

@ -0,0 +1,3 @@
from lib.util import get_electron_version
print(get_electron_version())

View file

@ -6,6 +6,7 @@ const got = require('got');
const semver = require('semver'); const semver = require('semver');
const { getCurrentBranch, ELECTRON_DIR } = require('../lib/utils'); const { getCurrentBranch, ELECTRON_DIR } = require('../lib/utils');
const { getElectronVersion } = require('../lib/get-version');
const rootPackageJson = require('../../package.json'); const rootPackageJson = require('../../package.json');
const { Octokit } = require('@octokit/rest'); const { Octokit } = require('@octokit/rest');
@ -34,7 +35,6 @@ const files = [
const jsonFields = [ const jsonFields = [
'name', 'name',
'version',
'repository', 'repository',
'description', 'description',
'license', 'license',
@ -44,6 +44,9 @@ const jsonFields = [
let npmTag = ''; let npmTag = '';
const currentElectronVersion = getElectronVersion();
const isNightlyElectronVersion = currentElectronVersion.includes('nightly');
new Promise((resolve, reject) => { new Promise((resolve, reject) => {
temp.mkdir('electron-npm', (err, dirPath) => { temp.mkdir('electron-npm', (err, dirPath) => {
if (err) { if (err) {
@ -68,6 +71,7 @@ new Promise((resolve, reject) => {
jsonFields.forEach((fieldName) => { jsonFields.forEach((fieldName) => {
packageJson[fieldName] = rootPackageJson[fieldName]; packageJson[fieldName] = rootPackageJson[fieldName];
}); });
packageJson.version = currentElectronVersion;
fs.writeFileSync( fs.writeFileSync(
path.join(tempDir, 'package.json'), path.join(tempDir, 'package.json'),
JSON.stringify(packageJson, null, 2) JSON.stringify(packageJson, null, 2)
@ -75,27 +79,27 @@ new Promise((resolve, reject) => {
return octokit.repos.listReleases({ return octokit.repos.listReleases({
owner: 'electron', owner: 'electron',
repo: rootPackageJson.version.indexOf('nightly') > 0 ? 'nightlies' : 'electron' repo: isNightlyElectronVersion ? 'nightlies' : 'electron'
}); });
}) })
.then((releases) => { .then((releases) => {
// download electron.d.ts from release // download electron.d.ts from release
const release = releases.data.find( const release = releases.data.find(
(release) => release.tag_name === `v${rootPackageJson.version}` (release) => release.tag_name === `v${currentElectronVersion}`
); );
if (!release) { if (!release) {
throw new Error(`cannot find release with tag v${rootPackageJson.version}`); throw new Error(`cannot find release with tag v${currentElectronVersion}`);
} }
return release; return release;
}) })
.then(async (release) => { .then(async (release) => {
const tsdAsset = release.assets.find((asset) => asset.name === 'electron.d.ts'); const tsdAsset = release.assets.find((asset) => asset.name === 'electron.d.ts');
if (!tsdAsset) { if (!tsdAsset) {
throw new Error(`cannot find electron.d.ts from v${rootPackageJson.version} release assets`); throw new Error(`cannot find electron.d.ts from v${currentElectronVersion} release assets`);
} }
const typingsContent = await getAssetContents( const typingsContent = await getAssetContents(
rootPackageJson.version.indexOf('nightly') > 0 ? 'nightlies' : 'electron', isNightlyElectronVersion ? 'nightlies' : 'electron',
tsdAsset.id tsdAsset.id
); );
@ -106,11 +110,11 @@ new Promise((resolve, reject) => {
.then(async (release) => { .then(async (release) => {
const checksumsAsset = release.assets.find((asset) => asset.name === 'SHASUMS256.txt'); const checksumsAsset = release.assets.find((asset) => asset.name === 'SHASUMS256.txt');
if (!checksumsAsset) { if (!checksumsAsset) {
throw new Error(`cannot find SHASUMS256.txt from v${rootPackageJson.version} release assets`); throw new Error(`cannot find SHASUMS256.txt from v${currentElectronVersion} release assets`);
} }
const checksumsContent = await getAssetContents( const checksumsContent = await getAssetContents(
rootPackageJson.version.indexOf('nightly') > 0 ? 'nightlies' : 'electron', isNightlyElectronVersion ? 'nightlies' : 'electron',
checksumsAsset.id checksumsAsset.id
); );
@ -127,7 +131,7 @@ new Promise((resolve, reject) => {
.then(async (release) => { .then(async (release) => {
const currentBranch = await getCurrentBranch(); const currentBranch = await getCurrentBranch();
if (release.tag_name.indexOf('nightly') > 0) { if (isNightlyElectronVersion) {
// TODO(main-migration): Simplify once main branch is renamed. // TODO(main-migration): Simplify once main branch is renamed.
if (currentBranch === 'master' || currentBranch === 'main') { if (currentBranch === 'master' || currentBranch === 'main') {
// Nightlies get published to their own module, so they should be tagged as latest // Nightlies get published to their own module, so they should be tagged as latest
@ -164,7 +168,7 @@ new Promise((resolve, reject) => {
.then(() => childProcess.execSync('npm pack', { cwd: tempDir })) .then(() => childProcess.execSync('npm pack', { cwd: tempDir }))
.then(() => { .then(() => {
// test that the package can install electron prebuilt from github release // test that the package can install electron prebuilt from github release
const tarballPath = path.join(tempDir, `${rootPackageJson.name}-${rootPackageJson.version}.tgz`); const tarballPath = path.join(tempDir, `${rootPackageJson.name}-${currentElectronVersion}.tgz`);
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const result = childProcess.spawnSync('npm', ['install', tarballPath, '--force', '--silent'], { const result = childProcess.spawnSync('npm', ['install', tarballPath, '--force', '--silent'], {
env: { ...process.env, electron_config_cache: tempDir }, env: { ...process.env, electron_config_cache: tempDir },
@ -190,7 +194,7 @@ new Promise((resolve, reject) => {
}); });
}) })
.then((tarballPath) => { .then((tarballPath) => {
const existingVersionJSON = childProcess.execSync(`npm view electron@${rootPackageJson.version} --json`).toString('utf-8'); const existingVersionJSON = childProcess.execSync(`npm view electron@${currentElectronVersion} --json`).toString('utf-8');
// It's possible this is a re-run and we already have published the package, if not we just publish like normal // It's possible this is a re-run and we already have published the package, if not we just publish like normal
if (!existingVersionJSON) { if (!existingVersionJSON) {
childProcess.execSync(`npm publish ${tarballPath} --tag ${npmTag} --otp=${process.env.ELECTRON_NPM_OTP}`); childProcess.execSync(`npm publish ${tarballPath} --tag ${npmTag} --otp=${process.env.ELECTRON_NPM_OTP}`);
@ -198,22 +202,21 @@ new Promise((resolve, reject) => {
}) })
.then(() => { .then(() => {
const currentTags = JSON.parse(childProcess.execSync('npm show electron dist-tags --json').toString()); const currentTags = JSON.parse(childProcess.execSync('npm show electron dist-tags --json').toString());
const localVersion = rootPackageJson.version; const parsedLocalVersion = semver.parse(currentElectronVersion);
const parsedLocalVersion = semver.parse(localVersion);
if (rootPackageJson.name === 'electron') { if (rootPackageJson.name === 'electron') {
// We should only customly add dist tags for non-nightly releases where the package name is still // We should only customly add dist tags for non-nightly releases where the package name is still
// "electron" // "electron"
if (parsedLocalVersion.prerelease.length === 0 && if (parsedLocalVersion.prerelease.length === 0 &&
semver.gt(localVersion, currentTags.latest)) { semver.gt(currentElectronVersion, currentTags.latest)) {
childProcess.execSync(`npm dist-tag add electron@${localVersion} latest --otp=${process.env.ELECTRON_NPM_OTP}`); childProcess.execSync(`npm dist-tag add electron@${currentElectronVersion} latest --otp=${process.env.ELECTRON_NPM_OTP}`);
} }
if (parsedLocalVersion.prerelease[0] === 'beta' && if (parsedLocalVersion.prerelease[0] === 'beta' &&
semver.gt(localVersion, currentTags.beta)) { semver.gt(currentElectronVersion, currentTags.beta)) {
childProcess.execSync(`npm dist-tag add electron@${localVersion} beta --otp=${process.env.ELECTRON_NPM_OTP}`); childProcess.execSync(`npm dist-tag add electron@${currentElectronVersion} beta --otp=${process.env.ELECTRON_NPM_OTP}`);
} }
if (parsedLocalVersion.prerelease[0] === 'alpha' && if (parsedLocalVersion.prerelease[0] === 'alpha' &&
semver.gt(localVersion, currentTags.alpha)) { semver.gt(currentElectronVersion, currentTags.alpha)) {
childProcess.execSync(`npm dist-tag add electron@${localVersion} alpha --otp=${process.env.ELECTRON_NPM_OTP}`); childProcess.execSync(`npm dist-tag add electron@${currentElectronVersion} alpha --otp=${process.env.ELECTRON_NPM_OTP}`);
} }
} }
}) })

View file

@ -18,26 +18,6 @@ require('colors');
const pass = '✓'.green; const pass = '✓'.green;
const fail = '✗'.red; const fail = '✗'.red;
function getLastBumpCommit (tag) {
const data = execSync(`git log -n1 --grep "Bump ${tag}" --format='format:{"hash": "%H", "message": "%s"}'`).toString();
return JSON.parse(data);
}
async function revertBumpCommit (tag) {
const branch = await getCurrentBranch();
const commitToRevert = getLastBumpCommit(tag).hash;
await GitProcess.exec(['pull', '--rebase']);
await GitProcess.exec(['revert', commitToRevert], ELECTRON_DIR);
const pushDetails = await GitProcess.exec(['push', 'origin', `HEAD:${branch}`, '--follow-tags'], ELECTRON_DIR);
if (pushDetails.exitCode === 0) {
console.log(`${pass} successfully reverted release commit.`);
} else {
const error = GitProcess.parseError(pushDetails.stderr);
console.error(`${fail} could not push release commit: `, error);
process.exit(1);
}
}
async function deleteDraft (releaseId, targetRepo) { async function deleteDraft (releaseId, targetRepo) {
try { try {
const result = await octokit.repos.getRelease({ const result = await octokit.repos.getRelease({
@ -80,9 +60,6 @@ async function cleanReleaseArtifacts () {
const releaseId = args.releaseID.length > 0 ? args.releaseID : null; const releaseId = args.releaseID.length > 0 ? args.releaseID : null;
const isNightly = args.tag.includes('nightly'); const isNightly = args.tag.includes('nightly');
// try to revert commit regardless of tag and draft deletion status
await revertBumpCommit(args.tag);
if (releaseId) { if (releaseId) {
if (isNightly) { if (isNightly) {
await deleteDraft(releaseId, 'nightlies'); await deleteDraft(releaseId, 'nightlies');

View file

@ -12,8 +12,6 @@ const args = require('minimist')(process.argv.slice(2), {
const fs = require('fs'); const fs = require('fs');
const { execSync } = require('child_process'); const { execSync } = require('child_process');
const got = require('got'); const got = require('got');
const pkg = require('../../package.json');
const pkgVersion = `v${pkg.version}`;
const path = require('path'); const path = require('path');
const temp = require('temp').track(); const temp = require('temp').track();
const { URL } = require('url'); const { URL } = require('url');
@ -25,8 +23,11 @@ const pass = '✓'.green;
const fail = '✗'.red; const fail = '✗'.red;
const { ELECTRON_DIR } = require('../lib/utils'); const { ELECTRON_DIR } = require('../lib/utils');
const { getElectronVersion } = require('../lib/get-version');
const getUrlHash = require('./get-url-hash'); const getUrlHash = require('./get-url-hash');
const pkgVersion = `v${getElectronVersion()}`;
const octokit = new Octokit({ const octokit = new Octokit({
auth: process.env.ELECTRON_GITHUB_TOKEN auth: process.env.ELECTRON_GITHUB_TOKEN
}); });

View file

@ -1,17 +1,10 @@
#!/usr/bin/env node #!/usr/bin/env node
const { GitProcess } = require('dugite');
const { promises: fs } = require('fs');
const semver = require('semver'); const semver = require('semver');
const path = require('path');
const minimist = require('minimist'); const minimist = require('minimist');
const { ELECTRON_DIR } = require('../lib/utils'); const { getElectronVersion } = require('../lib/get-version');
const versionUtils = require('./version-utils'); const versionUtils = require('./version-utils');
const supported = path.resolve(ELECTRON_DIR, 'docs', 'tutorial', 'support.md');
const writeFile = fs.writeFile;
const readFile = fs.readFile;
function parseCommandLine () { function parseCommandLine () {
let help; let help;
@ -37,7 +30,7 @@ function parseCommandLine () {
// run the script // run the script
async function main () { async function main () {
const opts = parseCommandLine(); const opts = parseCommandLine();
const currentVersion = await versionUtils.getElectronVersion(); const currentVersion = getElectronVersion();
const version = await nextVersion(opts.bump, currentVersion); const version = await nextVersion(opts.bump, currentVersion);
const parsed = semver.parse(version); const parsed = semver.parse(version);
@ -54,20 +47,6 @@ async function main () {
return 0; return 0;
} }
if (shouldUpdateSupported(opts.bump, currentVersion, version)) {
await updateSupported(version, supported);
}
// update all version-related files
await Promise.all([
updateVersion(version),
updatePackageJSON(version),
updateWinRC(components)
]);
// commit all updated version-related files
await commitVersionBump(version);
console.log(`Bumped to version: ${version}`); console.log(`Bumped to version: ${version}`);
} }
@ -118,10 +97,6 @@ async function nextVersion (bumpType, version) {
return version; return version;
} }
function shouldUpdateSupported (bump, current, version) {
return isMajorStable(bump, current) || isMajorNightly(version, current);
}
function isMajorStable (bump, currentVersion) { function isMajorStable (bump, currentVersion) {
if (versionUtils.isBeta(currentVersion) && (bump === 'stable')) return true; if (versionUtils.isBeta(currentVersion) && (bump === 'stable')) return true;
return false; return false;
@ -134,59 +109,6 @@ function isMajorNightly (version, currentVersion) {
return false; return false;
} }
// update VERSION file with latest release info
async function updateVersion (version) {
const versionPath = path.resolve(ELECTRON_DIR, 'ELECTRON_VERSION');
await writeFile(versionPath, version, 'utf8');
}
// update package metadata files with new version
async function updatePackageJSON (version) {
const filePath = path.resolve(ELECTRON_DIR, 'package.json');
const file = require(filePath);
file.version = version;
await writeFile(filePath, JSON.stringify(file, null, 2));
}
// push bump commit to release branch
async function commitVersionBump (version) {
const gitArgs = ['commit', '-a', '-m', `Bump v${version}`, '-n'];
await GitProcess.exec(gitArgs, ELECTRON_DIR);
}
// updates electron.rc file with new semver values
async function updateWinRC (components) {
const filePath = path.resolve(ELECTRON_DIR, 'shell', 'browser', 'resources', 'win', 'electron.rc');
const data = await readFile(filePath, 'utf8');
const arr = data.split('\n');
arr.forEach((line, idx) => {
if (line.includes('FILEVERSION')) {
arr[idx] = ` FILEVERSION ${versionUtils.makeVersion(components, ',', versionUtils.preType.PARTIAL)}`;
arr[idx + 1] = ` PRODUCTVERSION ${versionUtils.makeVersion(components, ',', versionUtils.preType.PARTIAL)}`;
} else if (line.includes('FileVersion')) {
arr[idx] = ` VALUE "FileVersion", "${versionUtils.makeVersion(components, '.')}"`;
arr[idx + 5] = ` VALUE "ProductVersion", "${versionUtils.makeVersion(components, '.')}"`;
}
});
await writeFile(filePath, arr.join('\n'));
}
// updates support.md file with new semver values (stable only)
async function updateSupported (version, filePath) {
const v = parseInt(version);
const newVersions = [`* ${v}.x.y`, `* ${v - 1}.x.y`, `* ${v - 2}.x.y`, `* ${v - 3}.x.y`];
const contents = await readFile(filePath, 'utf8');
const previousVersions = contents.split('\n').filter((elem) => {
return (/[^\n]*\.x\.y[^\n]*/).test(elem);
}, []);
const newContents = previousVersions.reduce((contents, current, i) => {
return contents.replace(current, newVersions[i]);
}, contents);
await writeFile(filePath, newContents, 'utf8');
}
if (process.mainModule === module) { if (process.mainModule === module) {
main().catch((error) => { main().catch((error) => {
console.error(error); console.error(error);
@ -194,4 +116,4 @@ if (process.mainModule === module) {
}); });
} }
module.exports = { nextVersion, shouldUpdateSupported, updateSupported }; module.exports = { nextVersion };

View file

@ -68,12 +68,6 @@ async function nextBeta (v) {
return tags.length === 0 ? `${next}-beta.1` : semver.inc(tags.pop(), 'prerelease'); return tags.length === 0 ? `${next}-beta.1` : semver.inc(tags.pop(), 'prerelease');
} }
async function getElectronVersion () {
const versionPath = path.resolve(ELECTRON_DIR, 'ELECTRON_VERSION');
const version = await readFile(versionPath, 'utf8');
return version.trim();
}
async function nextNightly (v) { async function nextNightly (v) {
let next = semver.valid(semver.coerce(v)); let next = semver.valid(semver.coerce(v));
const pre = `nightly.${getCurrentDate()}`; const pre = `nightly.${getCurrentDate()}`;
@ -114,7 +108,6 @@ module.exports = {
nextAlpha, nextAlpha,
nextBeta, nextBeta,
makeVersion, makeVersion,
getElectronVersion,
nextNightly, nextNightly,
preType preType
}; };

View file

@ -1,15 +1,9 @@
import { expect } from 'chai'; import { expect } from 'chai';
import { GitProcess, IGitExecutionOptions, IGitResult } from 'dugite'; import { GitProcess, IGitExecutionOptions, IGitResult } from 'dugite';
import { nextVersion, shouldUpdateSupported, updateSupported } from '../script/release/version-bumper'; import { nextVersion } from '../script/release/version-bumper';
import * as utils from '../script/release/version-utils'; import * as utils from '../script/release/version-utils';
import * as sinon from 'sinon'; import * as sinon from 'sinon';
import { ifdescribe } from './spec-helpers'; import { ifdescribe } from './spec-helpers';
const { promises: fs } = require('fs');
const path = require('path');
const fixtureDir = path.resolve(__dirname, 'fixtures', 'version-bumper', 'fixture_support.md');
const readFile = fs.readFile;
const writeFile = fs.writeFile;
class GitFake { class GitFake {
branches: { branches: {
@ -96,94 +90,6 @@ describe('version-bumper', () => {
}); });
}); });
describe('updateSupported', () => {
let restore: any;
before(async () => {
restore = await readFile(fixtureDir, 'utf8');
});
afterEach(async () => {
await writeFile(fixtureDir, restore, 'utf8');
});
it('updates correctly when a new stable version is promoted from beta', async () => {
const version = '4.0.0';
const currentVersion = '4.0.0-beta.29';
if (shouldUpdateSupported('stable', currentVersion, version)) {
await updateSupported(version, fixtureDir);
}
const contents = await readFile(fixtureDir, 'utf8');
expect(contents).to.contain('4.x.y\n* 3.x.y\n* 2.x.y');
});
it('should not update when a new stable patch version is promoted', async () => {
const version = '3.0.1';
const currentVersion = '3.0.0';
if (shouldUpdateSupported('stable', currentVersion, version)) {
await updateSupported(version, fixtureDir);
}
const contents = await readFile(fixtureDir, 'utf8');
expect(contents).to.contain('3.x.y\n* 2.x.y\n* 1.x.y');
});
it('should not update when a new stable minor version is promoted', async () => {
const version = '3.1.0';
const currentVersion = '3.0.0';
if (shouldUpdateSupported('minor', currentVersion, version)) {
await updateSupported(version, fixtureDir);
}
const contents = await readFile(fixtureDir, 'utf8');
expect(contents).to.contain('3.x.y\n* 2.x.y\n* 1.x.y');
});
it('should not update when a new beta.1 version is promoted', async () => {
const version = '5.0.0-beta.1';
const currentVersion = '4.0.0-beta.29';
if (shouldUpdateSupported('beta', currentVersion, version)) {
await updateSupported(version, fixtureDir);
}
const contents = await readFile(fixtureDir, 'utf8');
expect(contents).to.contain('3.x.y\n* 2.x.y\n* 1.x.y');
});
it('should not update when a new beta.12 version is promoted', async () => {
const version = '4.0.0-beta.12';
const currentVersion = '4.0.0-beta.11';
if (shouldUpdateSupported('beta', currentVersion, version)) {
await updateSupported(version, fixtureDir);
}
const contents = await readFile(fixtureDir, 'utf8');
expect(contents).to.contain('3.x.y\n* 2.x.y\n* 1.x.y');
});
it('should update when a new major nightly version is promoted', async () => {
const version = '4.0.0-nightly.19950901';
const currentVersion = '3.0.0-nightly.19950828';
if (shouldUpdateSupported('nightly', currentVersion, version)) {
await updateSupported(version, fixtureDir);
}
const contents = await readFile(fixtureDir, 'utf8');
expect(contents).to.contain('4.x.y\n* 3.x.y\n* 2.x.y');
});
it('should not update when a new nightly version is promoted', async () => {
const version = '3.0.0-nightly.19950901';
const currentVersion = '3.0.0-nightly.19950828';
if (shouldUpdateSupported('nightly', currentVersion, version)) {
await updateSupported(version, fixtureDir);
}
const contents = await readFile(fixtureDir, 'utf8');
expect(contents).to.contain('3.x.y\n* 2.x.y\n* 1.x.y');
});
});
// On macOS Circle CI we don't have a real git environment due to running // On macOS Circle CI we don't have a real git environment due to running
// gclient sync on a linux machine. These tests therefore don't run as expected. // gclient sync on a linux machine. These tests therefore don't run as expected.
ifdescribe(!(process.platform === 'linux' && process.arch.indexOf('arm') === 0) && process.platform !== 'darwin')('nextVersion', () => { ifdescribe(!(process.platform === 'linux' && process.arch.indexOf('arm') === 0) && process.platform !== 'darwin')('nextVersion', () => {