electron/script/release/publish-to-npm.js

184 lines
6.1 KiB
JavaScript
Raw Normal View History

2020-03-20 20:28:31 +00:00
const temp = require('temp');
const fs = require('fs');
const path = require('path');
const childProcess = require('child_process');
const { getCurrentBranch, ELECTRON_DIR } = require('../lib/utils');
const request = require('request');
const semver = require('semver');
const rootPackageJson = require('../../package.json');
const { Octokit } = require('@octokit/rest');
const octokit = new Octokit({
userAgent: 'electron-npm-publisher'
2020-03-20 20:28:31 +00:00
});
2018-08-17 00:08:52 +00:00
if (!process.env.ELECTRON_NPM_OTP) {
2020-03-20 20:28:31 +00:00
console.error('Please set ELECTRON_NPM_OTP');
process.exit(1);
2018-08-17 00:08:52 +00:00
}
2020-03-20 20:28:31 +00:00
let tempDir;
temp.track(); // track and cleanup files at exit
const files = [
'cli.js',
'index.js',
'install.js',
'package.json',
'README.md',
'LICENSE'
2020-03-20 20:28:31 +00:00
];
const jsonFields = [
'name',
'version',
'repository',
'description',
'license',
'author',
'keywords'
2020-03-20 20:28:31 +00:00
];
2020-03-20 20:28:31 +00:00
let npmTag = '';
new Promise((resolve, reject) => {
temp.mkdir('electron-npm', (err, dirPath) => {
if (err) {
2020-03-20 20:28:31 +00:00
reject(err);
} else {
2020-03-20 20:28:31 +00:00
resolve(dirPath);
}
2020-03-20 20:28:31 +00:00
});
})
2018-09-13 16:10:51 +00:00
.then((dirPath) => {
2020-03-20 20:28:31 +00:00
tempDir = dirPath;
2018-09-13 16:10:51 +00:00
// copy files from `/npm` to temp directory
files.forEach((name) => {
2020-03-20 20:28:31 +00:00
const noThirdSegment = name === 'README.md' || name === 'LICENSE';
2018-09-13 16:10:51 +00:00
fs.writeFileSync(
path.join(tempDir, name),
fs.readFileSync(path.join(ELECTRON_DIR, noThirdSegment ? '' : 'npm', name))
2020-03-20 20:28:31 +00:00
);
});
2018-09-13 16:10:51 +00:00
// copy from root package.json to temp/package.json
2020-03-20 20:28:31 +00:00
const packageJson = require(path.join(tempDir, 'package.json'));
2018-09-13 16:10:51 +00:00
jsonFields.forEach((fieldName) => {
2020-03-20 20:28:31 +00:00
packageJson[fieldName] = rootPackageJson[fieldName];
});
fs.writeFileSync(
2018-09-13 16:10:51 +00:00
path.join(tempDir, 'package.json'),
JSON.stringify(packageJson, null, 2)
2020-03-20 20:28:31 +00:00
);
return octokit.repos.listReleases({
2018-09-13 16:10:51 +00:00
owner: 'electron',
repo: rootPackageJson.version.indexOf('nightly') > 0 ? 'nightlies' : 'electron'
2020-03-20 20:28:31 +00:00
});
})
2018-09-13 16:10:51 +00:00
.then((releases) => {
// download electron.d.ts from release
2018-09-13 16:10:51 +00:00
const release = releases.data.find(
(release) => release.tag_name === `v${rootPackageJson.version}`
2020-03-20 20:28:31 +00:00
);
2018-09-13 16:10:51 +00:00
if (!release) {
2020-03-20 20:28:31 +00:00
throw new Error(`cannot find release with tag v${rootPackageJson.version}`);
2018-09-13 16:10:51 +00:00
}
2020-03-20 20:28:31 +00:00
return release;
2018-09-13 16:10:51 +00:00
})
.then((release) => {
2020-03-20 20:28:31 +00:00
const tsdAsset = release.assets.find((asset) => asset.name === 'electron.d.ts');
2018-09-13 16:10:51 +00:00
if (!tsdAsset) {
2020-03-20 20:28:31 +00:00
throw new Error(`cannot find electron.d.ts from v${rootPackageJson.version} release assets`);
2018-09-13 16:10:51 +00:00
}
return new Promise((resolve, reject) => {
request.get({
url: tsdAsset.url,
headers: {
accept: 'application/octet-stream',
2018-09-13 16:10:51 +00:00
'user-agent': 'electron-npm-publisher'
}
}, (err, response, body) => {
if (err || response.statusCode !== 200) {
2020-03-20 20:28:31 +00:00
reject(err || new Error('Cannot download electron.d.ts'));
2018-09-13 16:10:51 +00:00
} else {
2020-03-20 20:28:31 +00:00
fs.writeFileSync(path.join(tempDir, 'electron.d.ts'), body);
resolve(release);
2018-09-13 16:10:51 +00:00
}
2020-03-20 20:28:31 +00:00
});
});
})
2018-09-13 16:10:51 +00:00
.then(async (release) => {
2020-03-20 20:28:31 +00:00
const currentBranch = await getCurrentBranch();
2018-09-13 16:10:51 +00:00
if (release.tag_name.indexOf('nightly') > 0) {
// TODO(main-migration): Simplify once main branch is renamed.
if (currentBranch === 'master' || currentBranch === 'main') {
// Nightlies get published to their own module, so they should be tagged as latest
2020-03-20 20:28:31 +00:00
npmTag = 'latest';
2018-09-13 16:10:51 +00:00
} else {
2020-03-20 20:28:31 +00:00
npmTag = `nightly-${currentBranch}`;
2018-09-13 16:10:51 +00:00
}
2020-03-20 20:28:31 +00:00
const currentJson = JSON.parse(fs.readFileSync(path.join(tempDir, 'package.json'), 'utf8'));
currentJson.name = 'electron-nightly';
rootPackageJson.name = 'electron-nightly';
fs.writeFileSync(
path.join(tempDir, 'package.json'),
JSON.stringify(currentJson, null, 2)
2020-03-20 20:28:31 +00:00
);
} else {
if (currentBranch === 'master' || currentBranch === 'main') {
// This should never happen, main releases should be nightly releases
// this is here just-in-case
throw new Error('Unreachable release phase, can\'t tag a non-nightly release on the main branch');
} else if (!release.prerelease) {
// Tag the release with a `2-0-x` style tag
2020-03-20 20:28:31 +00:00
npmTag = currentBranch;
} else {
// Tag the release with a `beta-3-0-x` style tag
2020-03-20 20:28:31 +00:00
npmTag = `beta-${currentBranch}`;
}
}
2018-09-13 16:10:51 +00:00
})
.then(() => childProcess.execSync('npm pack', { cwd: tempDir }))
.then(() => {
// test that the package can install electron prebuilt from github release
2020-03-20 20:28:31 +00:00
const tarballPath = path.join(tempDir, `${rootPackageJson.name}-${rootPackageJson.version}.tgz`);
2018-09-13 16:10:51 +00:00
return new Promise((resolve, reject) => {
childProcess.execSync(`npm install ${tarballPath} --force --silent`, {
env: Object.assign({}, process.env, { electron_config_cache: tempDir }),
cwd: tempDir
2020-03-20 20:28:31 +00:00
});
resolve(tarballPath);
});
})
.then((tarballPath) => {
const existingVersionJSON = childProcess.execSync(`npm view electron@${rootPackageJson.version} --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
if (!existingVersionJSON) {
childProcess.execSync(`npm publish ${tarballPath} --tag ${npmTag} --otp=${process.env.ELECTRON_NPM_OTP}`);
}
})
.then(() => {
2020-03-20 20:28:31 +00:00
const currentTags = JSON.parse(childProcess.execSync('npm show electron dist-tags --json').toString());
const localVersion = rootPackageJson.version;
const parsedLocalVersion = semver.parse(localVersion);
if (rootPackageJson.name === 'electron') {
// We should only customly add dist tags for non-nightly releases where the package name is still
// "electron"
if (parsedLocalVersion.prerelease.length === 0 &&
semver.gt(localVersion, currentTags.latest)) {
2020-03-20 20:28:31 +00:00
childProcess.execSync(`npm dist-tag add electron@${localVersion} latest --otp=${process.env.ELECTRON_NPM_OTP}`);
}
if (parsedLocalVersion.prerelease[0] === 'beta' &&
semver.gt(localVersion, currentTags.beta)) {
2020-03-20 20:28:31 +00:00
childProcess.execSync(`npm dist-tag add electron@${localVersion} beta --otp=${process.env.ELECTRON_NPM_OTP}`);
}
}
})
2018-09-13 16:10:51 +00:00
.catch((err) => {
2020-03-20 20:28:31 +00:00
console.error(`Error: ${err}`);
process.exit(1);
});