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')({ headers: { 'User-Agent': 'electron-npm-publisher' } }); if (!process.env.ELECTRON_NPM_OTP) { console.error('Please set ELECTRON_NPM_OTP'); process.exit(1); } let tempDir; temp.track(); // track and cleanup files at exit const files = [ 'cli.js', 'index.js', 'install.js', 'package.json', 'README.md', 'LICENSE' ]; const jsonFields = [ 'name', 'version', 'repository', 'description', 'license', 'author', 'keywords' ]; let npmTag = ''; new Promise((resolve, reject) => { temp.mkdir('electron-npm', (err, dirPath) => { if (err) { reject(err); } else { resolve(dirPath); } }); }) .then((dirPath) => { tempDir = dirPath; // copy files from `/npm` to temp directory files.forEach((name) => { const noThirdSegment = name === 'README.md' || name === 'LICENSE'; fs.writeFileSync( path.join(tempDir, name), fs.readFileSync(path.join(ELECTRON_DIR, noThirdSegment ? '' : 'npm', name)) ); }); // copy from root package.json to temp/package.json const packageJson = require(path.join(tempDir, 'package.json')); jsonFields.forEach((fieldName) => { packageJson[fieldName] = rootPackageJson[fieldName]; }); fs.writeFileSync( path.join(tempDir, 'package.json'), JSON.stringify(packageJson, null, 2) ); return octokit.repos.listReleases({ owner: 'electron', repo: rootPackageJson.version.indexOf('nightly') > 0 ? 'nightlies' : 'electron' }); }) .then((releases) => { // download electron.d.ts from release const release = releases.data.find( (release) => release.tag_name === `v${rootPackageJson.version}` ); if (!release) { throw new Error(`cannot find release with tag v${rootPackageJson.version}`); } return release; }) .then((release) => { const tsdAsset = release.assets.find((asset) => asset.name === 'electron.d.ts'); if (!tsdAsset) { throw new Error(`cannot find electron.d.ts from v${rootPackageJson.version} release assets`); } return new Promise((resolve, reject) => { request.get({ url: tsdAsset.url, headers: { accept: 'application/octet-stream', 'user-agent': 'electron-npm-publisher' } }, (err, response, body) => { if (err || response.statusCode !== 200) { reject(err || new Error('Cannot download electron.d.ts')); } else { fs.writeFileSync(path.join(tempDir, 'electron.d.ts'), body); resolve(release); } }); }); }) .then(async (release) => { const currentBranch = await getCurrentBranch(); if (release.tag_name.indexOf('nightly') > 0) { if (currentBranch === 'master') { // Nightlies get published to their own module, so master nightlies should be tagged as latest npmTag = 'latest'; } else { npmTag = `nightly-${currentBranch}`; } 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) ); } else { if (currentBranch === 'master') { // This should never happen, master releases should be nightly releases // this is here just-in-case npmTag = 'master'; } else if (!release.prerelease) { // Tag the release with a `2-0-x` style tag npmTag = currentBranch; } else { // Tag the release with a `beta-3-0-x` style tag npmTag = `beta-${currentBranch}`; } } }) .then(() => childProcess.execSync('npm pack', { cwd: tempDir })) .then(() => { // test that the package can install electron prebuilt from github release const tarballPath = path.join(tempDir, `${rootPackageJson.name}-${rootPackageJson.version}.tgz`); return new Promise((resolve, reject) => { childProcess.execSync(`npm install ${tarballPath} --force --silent`, { env: Object.assign({}, process.env, { electron_config_cache: tempDir }), cwd: tempDir }); resolve(tarballPath); }); }) .then((tarballPath) => childProcess.execSync(`npm publish ${tarballPath} --tag ${npmTag} --otp=${process.env.ELECTRON_NPM_OTP}`)) .then(() => { 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)) { 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)) { childProcess.execSync(`npm dist-tag add electron@${localVersion} beta --otp=${process.env.ELECTRON_NPM_OTP}`); } } }) .catch((err) => { console.error(`Error: ${err}`); process.exit(1); });