mirror of
https://github.com/wavetermdev/xterm.js.git
synced 2026-04-22 15:25:47 -07:00
236 lines
7.9 KiB
JavaScript
236 lines
7.9 KiB
JavaScript
/**
|
|
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
|
|
* @license MIT
|
|
*/
|
|
|
|
const cp = require('child_process');
|
|
const fs = require('fs');
|
|
const os = require('os');
|
|
const path = require('path');
|
|
|
|
// Setup auth
|
|
if (process.env['NPM_AUTH_TOKEN']) {
|
|
fs.writeFileSync(`${process.env['HOME']}/.npmrc`, `//registry.npmjs.org/:_authToken=${process.env['NPM_AUTH_TOKEN']}`);
|
|
}
|
|
|
|
log('Configuration:', 'green')
|
|
const isDryRun = process.argv.includes('--dry');
|
|
if (isDryRun) {
|
|
log(' Publish dry run');
|
|
}
|
|
|
|
const allAddons = process.argv.includes('--all-addons');
|
|
if (allAddons) {
|
|
log(' Publish all addons');
|
|
}
|
|
|
|
const repoCommit = getRepoCommit();
|
|
const changedFiles = getChangedFilesInCommit('HEAD');
|
|
|
|
// Always publish xterm, technically this isn't needed if
|
|
// `changedFiles.some(e => e.search(/^addons\//)`, but it's here for convenience to get the right
|
|
// peer dependencies for addons.
|
|
const result = checkAndPublishPackage(path.resolve(__dirname, '..'), repoCommit, undefined, true);
|
|
const isStableRelease = result.isStableRelease;
|
|
const peerDependencies = result.nextVersion.includes('beta') ? {
|
|
'@xterm/xterm': `^${result.nextVersion}`,
|
|
} : undefined;
|
|
checkAndPublishPackage(path.resolve(__dirname, '../headless'), repoCommit);
|
|
|
|
// Addon peer dependencies
|
|
|
|
// Publish addons if any files were changed inside of the addon
|
|
const addonPackageDirs = [
|
|
path.resolve(__dirname, '../addons/addon-attach'),
|
|
path.resolve(__dirname, '../addons/addon-clipboard'),
|
|
path.resolve(__dirname, '../addons/addon-fit'),
|
|
path.resolve(__dirname, '../addons/addon-image'),
|
|
path.resolve(__dirname, '../addons/addon-ligatures'),
|
|
path.resolve(__dirname, '../addons/addon-progress'),
|
|
path.resolve(__dirname, '../addons/addon-search'),
|
|
path.resolve(__dirname, '../addons/addon-serialize'),
|
|
path.resolve(__dirname, '../addons/addon-unicode11'),
|
|
path.resolve(__dirname, '../addons/addon-unicode-graphemes'),
|
|
path.resolve(__dirname, '../addons/addon-web-fonts'),
|
|
path.resolve(__dirname, '../addons/addon-web-links'),
|
|
path.resolve(__dirname, '../addons/addon-webgl')
|
|
];
|
|
log(`Checking if addons need to be published`, 'green');
|
|
for (const p of addonPackageDirs) {
|
|
const addon = path.basename(p);
|
|
if (allAddons || changedFiles.some(e => e.includes(addon))) {
|
|
checkAndPublishPackage(p, repoCommit, peerDependencies);
|
|
}
|
|
}
|
|
|
|
// Publish website if it's a stable release
|
|
if (isStableRelease) {
|
|
updateWebsite();
|
|
}
|
|
|
|
function checkAndPublishPackage(packageDir, repoCommit, peerDependencies, updateVersionTs = false) {
|
|
const packageJson = require(path.join(packageDir, 'package.json'));
|
|
|
|
// Determine if this is a stable or beta release
|
|
const publishedVersions = getPublishedVersions(packageJson);
|
|
const isStableRelease = !publishedVersions.includes(packageJson.version);
|
|
|
|
// Get the next version
|
|
let nextVersion = isStableRelease ? packageJson.version : getNextBetaVersion(packageJson);
|
|
log(`Publishing version: ${nextVersion}`, 'green');
|
|
|
|
// Update Version.ts with the new version
|
|
if (updateVersionTs) {
|
|
const versionTsPath = path.join(packageDir, 'src/common/Version.ts');
|
|
const versionTsContent = fs.readFileSync(versionTsPath, 'utf8');
|
|
const updatedVersionTs = versionTsContent.replace(
|
|
/export const XTERM_VERSION = '[^']+';/,
|
|
`export const XTERM_VERSION = '${nextVersion}';`
|
|
);
|
|
fs.writeFileSync(versionTsPath, updatedVersionTs);
|
|
log(`Updated ${versionTsPath} to version ${nextVersion}`);
|
|
}
|
|
|
|
// Set the version in package.json
|
|
const packageJsonFile = path.join(packageDir, 'package.json');
|
|
packageJson.version = nextVersion;
|
|
|
|
// Set the commit in package.json
|
|
if (repoCommit) {
|
|
packageJson.commit = repoCommit;
|
|
log(`Set commit of ${packageJsonFile} to ${repoCommit}`);
|
|
} else {
|
|
throw new Error(`No commit set`);
|
|
}
|
|
|
|
// Set peer dependencies
|
|
if (peerDependencies) {
|
|
packageJson.peerDependencies = peerDependencies;
|
|
log(`Set peerDependencies of ${packageJsonFile} to ${JSON.stringify(peerDependencies)}`);
|
|
} else {
|
|
log(`Skipping peerDependencies`);
|
|
}
|
|
|
|
// Write new package.json
|
|
fs.writeFileSync(packageJsonFile, JSON.stringify(packageJson, null, 2));
|
|
|
|
// Publish
|
|
const args = ['publish', '--access', 'public'];
|
|
if (!isStableRelease) {
|
|
args.push('--tag', 'beta');
|
|
}
|
|
if (isDryRun) {
|
|
args.push('--dry-run');
|
|
}
|
|
log(`Spawn: npm ${args.join(' ')}`);
|
|
const result = cp.spawnSync('npm', args, {
|
|
cwd: packageDir,
|
|
stdio: 'inherit'
|
|
});
|
|
if (result.status) {
|
|
throw new Error(`Spawn exited with code ${result.status}`);
|
|
}
|
|
|
|
return { isStableRelease, nextVersion };
|
|
}
|
|
|
|
function getRepoCommit() {
|
|
const commitProcess = cp.spawnSync('git', ['log', '-1', '--format="%H"']);
|
|
if (commitProcess.stdout.length === 0 && commitProcess.stderr) {
|
|
const err = versionsProcess.stderr.toString();
|
|
throw new Error('Could not get repo commit\n' + err);
|
|
}
|
|
const output = commitProcess.stdout.toString().trim();
|
|
return output.replace(/^"/, '').replace(/"$/, '');
|
|
}
|
|
|
|
function getNextBetaVersion(packageJson) {
|
|
if (!/^\d+\.\d+\.\d+$/.exec(packageJson.version)) {
|
|
throw new Error('The package.json version must be of the form x.y.z');
|
|
}
|
|
const tag = 'beta';
|
|
const stableVersion = packageJson.version.split('.');
|
|
const nextStableVersion = `${stableVersion[0]}.${parseInt(stableVersion[1]) + 1}.0`;
|
|
const publishedVersions = getPublishedVersions(packageJson, nextStableVersion, tag);
|
|
if (publishedVersions.length === 0) {
|
|
return `${nextStableVersion}-${tag}.1`;
|
|
}
|
|
const latestPublishedVersion = publishedVersions.sort((a, b) => {
|
|
const aVersion = parseInt(a.slice(a.search(/\d+$/)));
|
|
const bVersion = parseInt(b.slice(b.search(/\d+$/)));
|
|
return aVersion > bVersion ? -1 : 1;
|
|
})[0];
|
|
const latestTagVersion = parseInt(latestPublishedVersion.slice(latestPublishedVersion.search(/\d+$/)), 10);
|
|
return `${nextStableVersion}-${tag}.${latestTagVersion + 1}`;
|
|
}
|
|
|
|
function asArray(value) {
|
|
return Array.isArray(value) ? value : [value];
|
|
}
|
|
|
|
function getPublishedVersions(packageJson, version, tag) {
|
|
const versionsProcess = cp.spawnSync(
|
|
os.platform === 'win32' ? 'npm.cmd' : 'npm',
|
|
['view', packageJson.name, 'versions', '--json'],
|
|
{ shell: true }
|
|
);
|
|
if (versionsProcess.stdout.length === 0 && versionsProcess.stderr) {
|
|
const err = versionsProcess.stderr.toString();
|
|
if (err.indexOf('404 Not Found - GET https://registry.npmjs.org/@xterm') > 0) {
|
|
return [];
|
|
}
|
|
throw new Error('Could not get published versions\n' + err);
|
|
}
|
|
const output = JSON.parse(versionsProcess.stdout);
|
|
if (typeof output === 'object' && !Array.isArray(output)) {
|
|
if (output.error?.code === 'E404') {
|
|
return [];
|
|
}
|
|
throw new Error('Could not get published versions\n' + output);
|
|
}
|
|
if (!output || Array.isArray(output) && output.length === 0) {
|
|
return [];
|
|
}
|
|
const versionsJson = asArray(output);
|
|
if (tag) {
|
|
return versionsJson.filter(v => !v.search(new RegExp(`${version}-${tag}.[0-9]+`)));
|
|
}
|
|
return versionsJson;
|
|
}
|
|
|
|
function getChangedFilesInCommit(commit) {
|
|
const args = ['log', '-m', '-1', '--name-only', `--pretty=format:`, commit];
|
|
const result = cp.spawnSync('git', args);
|
|
const output = result.stdout.toString();
|
|
const changedFiles = output.split('\n').filter(e => e.length > 0);
|
|
return changedFiles;
|
|
}
|
|
|
|
function updateWebsite() {
|
|
log('Updating website', 'green');
|
|
const cwd = fs.mkdtempSync(path.join(os.tmpdir(), 'website-'));
|
|
const packageJson = require(path.join(path.resolve(__dirname, '..'), 'package.json'));
|
|
if (!isDryRun) {
|
|
cp.spawnSync('sh', [path.join(__dirname, 'update-website.sh'), packageJson.version], { cwd, stdio: [process.stdin, process.stdout, process.stderr] });
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {string} message
|
|
*/
|
|
function log(message, color) {
|
|
let colorSequence = '';
|
|
switch (color) {
|
|
case 'green': {
|
|
colorSequence = '\x1b[32m';
|
|
break;
|
|
}
|
|
}
|
|
console.info([
|
|
`[\x1b[2m${new Date().toLocaleTimeString('en-GB')}\x1b[0m] `,
|
|
colorSequence,
|
|
message,
|
|
'\x1b[0m',
|
|
].join(''));
|
|
}
|