2018-04-17 21:42:31 +02:00
|
|
|
/// <reference types="node"/>
|
|
|
|
import { normalize } from "path";
|
|
|
|
import assert = require("assert");
|
|
|
|
import { readFileSync, writeFileSync } from "fs";
|
|
|
|
const args = process.argv.slice(2);
|
|
|
|
|
2015-07-15 03:09:42 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* A minimal description for a parsed package.json object.
|
|
|
|
*/
|
|
|
|
interface PackageJson {
|
|
|
|
name: string;
|
|
|
|
version: string;
|
|
|
|
keywords: string[];
|
|
|
|
}
|
|
|
|
|
|
|
|
function main(): void {
|
2018-04-17 21:42:31 +02:00
|
|
|
if (args.length < 3) {
|
|
|
|
console.log("Usage:");
|
|
|
|
console.log("\tnode configureNightly.js <dev|insiders> <package.json location> <file containing version>");
|
2015-07-15 03:09:42 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-04-17 21:42:31 +02:00
|
|
|
const tag = args[0];
|
2018-01-20 00:58:35 +01:00
|
|
|
if (tag !== "dev" && tag !== "insiders") {
|
|
|
|
throw new Error(`Unexpected tag name '${tag}'.`);
|
|
|
|
}
|
|
|
|
|
2015-07-15 03:09:42 +02:00
|
|
|
// Acquire the version from the package.json file and modify it appropriately.
|
2018-04-17 21:42:31 +02:00
|
|
|
const packageJsonFilePath = normalize(args[1]);
|
|
|
|
const packageJsonValue: PackageJson = JSON.parse(readFileSync(packageJsonFilePath).toString());
|
2015-07-15 03:09:42 +02:00
|
|
|
|
2017-07-19 23:47:25 +02:00
|
|
|
const { majorMinor, patch } = parsePackageJsonVersion(packageJsonValue.version);
|
2018-01-20 00:58:35 +01:00
|
|
|
const prereleasePatch = getPrereleasePatch(tag, patch);
|
2015-07-15 03:09:42 +02:00
|
|
|
|
|
|
|
// Acquire and modify the source file that exposes the version string.
|
2018-04-17 21:42:31 +02:00
|
|
|
const tsFilePath = normalize(args[2]);
|
|
|
|
const tsFileContents = readFileSync(tsFilePath).toString();
|
2018-01-20 00:58:35 +01:00
|
|
|
const modifiedTsFileContents = updateTsFile(tsFilePath, tsFileContents, majorMinor, patch, prereleasePatch);
|
2015-07-15 03:09:42 +02:00
|
|
|
|
|
|
|
// Ensure we are actually changing something - the user probably wants to know that the update failed.
|
|
|
|
if (tsFileContents === modifiedTsFileContents) {
|
2018-01-20 00:58:35 +01:00
|
|
|
let err = `\n '${tsFilePath}' was not updated while configuring for a prerelease publish for '${tag}'.\n `;
|
2017-07-19 23:47:25 +02:00
|
|
|
err += `Ensure that you have not already run this script; otherwise, erase your changes using 'git checkout -- "${tsFilePath}"'.`;
|
2018-01-20 00:58:35 +01:00
|
|
|
throw new Error(err + "\n");
|
2015-07-15 03:09:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Finally write the changes to disk.
|
2017-07-19 23:47:25 +02:00
|
|
|
// Modify the package.json structure
|
2018-01-20 00:58:35 +01:00
|
|
|
packageJsonValue.version = `${majorMinor}.${prereleasePatch}`;
|
2018-04-17 21:42:31 +02:00
|
|
|
writeFileSync(packageJsonFilePath, JSON.stringify(packageJsonValue, /*replacer:*/ undefined, /*space:*/ 4))
|
|
|
|
writeFileSync(tsFilePath, modifiedTsFileContents);
|
2015-07-15 03:09:42 +02:00
|
|
|
}
|
|
|
|
|
2017-07-19 23:47:25 +02:00
|
|
|
function updateTsFile(tsFilePath: string, tsFileContents: string, majorMinor: string, patch: string, nightlyPatch: string): string {
|
|
|
|
const majorMinorRgx = /export const versionMajorMinor = "(\d+\.\d+)"/;
|
|
|
|
const majorMinorMatch = majorMinorRgx.exec(tsFileContents);
|
2018-04-17 21:42:31 +02:00
|
|
|
assert(majorMinorMatch !== null, `The file seems to no longer have a string matching '${majorMinorRgx}'.`);
|
2017-07-19 23:47:25 +02:00
|
|
|
const parsedMajorMinor = majorMinorMatch[1];
|
2018-04-17 21:42:31 +02:00
|
|
|
assert(parsedMajorMinor === majorMinor, `versionMajorMinor does not match. ${tsFilePath}: '${parsedMajorMinor}'; package.json: '${majorMinor}'`);
|
2017-07-19 23:47:25 +02:00
|
|
|
|
2018-02-08 08:45:37 +01:00
|
|
|
const versionRgx = /export const version = `\$\{versionMajorMinor\}\.(\d)(-dev)?`;/;
|
2017-07-19 23:47:25 +02:00
|
|
|
const patchMatch = versionRgx.exec(tsFileContents);
|
2018-04-17 21:42:31 +02:00
|
|
|
assert(patchMatch !== null, "The file seems to no longer have a string matching " + versionRgx.toString());
|
2017-07-19 23:47:25 +02:00
|
|
|
const parsedPatch = patchMatch[1];
|
|
|
|
if (parsedPatch !== patch) {
|
|
|
|
throw new Error(`patch does not match. ${tsFilePath}: '${parsedPatch}; package.json: '${patch}'`);
|
2015-07-15 03:09:42 +02:00
|
|
|
}
|
|
|
|
|
2017-07-19 23:47:25 +02:00
|
|
|
return tsFileContents.replace(versionRgx, `export const version = \`\${versionMajorMinor}.${nightlyPatch}\`;`);
|
|
|
|
}
|
|
|
|
|
|
|
|
function parsePackageJsonVersion(versionString: string): { majorMinor: string, patch: string } {
|
|
|
|
const versionRgx = /(\d+\.\d+)\.(\d+)($|\-)/;
|
|
|
|
const match = versionString.match(versionRgx);
|
2018-04-17 21:42:31 +02:00
|
|
|
assert(match !== null, "package.json 'version' should match " + versionRgx.toString());
|
2017-07-19 23:47:25 +02:00
|
|
|
return { majorMinor: match[1], patch: match[2] };
|
|
|
|
}
|
|
|
|
|
|
|
|
/** e.g. 0-dev.20170707 */
|
2018-01-20 00:58:35 +01:00
|
|
|
function getPrereleasePatch(tag: string, plainPatch: string): string {
|
2015-07-15 03:09:42 +02:00
|
|
|
// We're going to append a representation of the current time at the end of the current version.
|
|
|
|
// String.prototype.toISOString() returns a 24-character string formatted as 'YYYY-MM-DDTHH:mm:ss.sssZ',
|
2015-07-23 21:32:17 +02:00
|
|
|
// but we'd prefer to just remove separators and limit ourselves to YYYYMMDD.
|
|
|
|
// UTC time will always be implicit here.
|
2015-07-15 03:09:42 +02:00
|
|
|
const now = new Date();
|
2015-07-23 21:32:17 +02:00
|
|
|
const timeStr = now.toISOString().replace(/:|T|\.|-/g, "").slice(0, 8);
|
2015-07-15 03:09:42 +02:00
|
|
|
|
2018-01-20 00:58:35 +01:00
|
|
|
return `${plainPatch}-${tag}.${timeStr}`;
|
2015-07-15 03:09:42 +02:00
|
|
|
}
|
|
|
|
|
2018-02-08 08:45:37 +01:00
|
|
|
main();
|