mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
ea9f533536
Before this commit, the release script would build the code, then update the version number, so the released code would have the previous release number instead of the current.
247 lines
7.8 KiB
JavaScript
247 lines
7.8 KiB
JavaScript
const package = require("../package.json");
|
|
const packageLock = require("../package-lock.json");
|
|
const readline = require("readline");
|
|
const fs = require("fs");
|
|
const exec = require("child_process").exec;
|
|
const chalk = require("chalk");
|
|
const branchName = require('current-git-branch');
|
|
|
|
const REL_NOTES_FILE = `release-notes.md`;
|
|
const branch = "master";
|
|
|
|
const rl = readline.createInterface({
|
|
input: process.stdin,
|
|
output: process.stdout
|
|
});
|
|
|
|
startRelease().then(() => {
|
|
rl.close();
|
|
});
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Relase Script
|
|
// -----------------------------------------------------------------------------
|
|
|
|
async function startRelease() {
|
|
// First check we are on master
|
|
if (branchName() !== branch) {
|
|
logError(`You shall not pass! You are not on the ${branch} branch!`)
|
|
return;
|
|
}
|
|
|
|
log(`*** Owl release script ***`);
|
|
log(`Current Version: ${package.version}`);
|
|
|
|
const STEPS = 11;
|
|
let step = 1;
|
|
// ---------------------------------------------------------------------------
|
|
log(`Step ${step++}/${STEPS}: Checking if code formatting is right...`)
|
|
const checkFormatting = await execCommand("npm run check-formatting");
|
|
if (checkFormatting !== 0) {
|
|
logError("Prettier format validation failed. Aborting.");
|
|
return;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
log(`Step ${step++}/${STEPS}: collecting info...`);
|
|
let next = await ask("Next version: ");
|
|
if (next[0] === 'v') next = next.substring(1);
|
|
let file = await ask(`Release notes (${REL_NOTES_FILE}): `);
|
|
file = file || REL_NOTES_FILE;
|
|
if (!fs.existsSync(`./${file}`)) {
|
|
const lastRelease = await getOutput("git log --grep='\\[REL\\]' -n 1 --pretty=%H");
|
|
const commitsSinceLastRelease = await getOutput(`git log ${lastRelease.trim()}..HEAD --pretty=%s`);
|
|
const commitsAsMdList = commitsSinceLastRelease.trim().split("\n").map(l => " - " + l).join("\n");
|
|
log(`${file} did not exist, created a template containing all commits since last release.`)
|
|
fs.writeFileSync(file, `# v${next}\n\n${commitsAsMdList}`);
|
|
const shouldContinue = await ask(`Check that the contents of ${file} is correct, then press y to continue: `);
|
|
if (shouldContinue.toLowerCase() !== "y") {
|
|
log("aborted");
|
|
return;
|
|
}
|
|
}
|
|
let content;
|
|
try {
|
|
content = await readFile("./" + file);
|
|
} catch (e) {
|
|
logSubContent(e.message);
|
|
logError("Cannot find release notes... Aborting");
|
|
return;
|
|
}
|
|
let shouldBeDraft = await ask(`Should be a draft [y/n] ? (n)`);
|
|
let draft = ""
|
|
if (shouldBeDraft.toLowerCase() === 'y') {
|
|
draft = "--draft";
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
log(`Step ${step++}/${STEPS}: running tests...`);
|
|
const testsResult = await execCommand("npm run test");
|
|
if (testsResult !== 0) {
|
|
logError("Test suite does not pass. Aborting.");
|
|
return;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
log(`Step ${step++}/${STEPS}: updating package.json...`);
|
|
await writeFile("package.json", JSON.stringify({...package, version: next}, null, 2) + "\n");
|
|
await writeFile("package-lock.json", JSON.stringify({...packageLock, version: next}, null, 2) + "\n");
|
|
await writeFile("./src/version.ts", `// do not modify manually. This file is generated by the release script.\nexport const version = "${next}";\n`);
|
|
|
|
// ---------------------------------------------------------------------------
|
|
log(`Step ${step++}/${STEPS}: building owl...`);
|
|
await execCommand("rm -rf dist/");
|
|
const buildResult = await execCommand("npm run build");
|
|
if (buildResult !== 0) {
|
|
logError("Build failed. Aborting.");
|
|
return;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
log(`Step ${step++}/${STEPS}: building devtools...`);
|
|
const chromeResult = await execCommand("npm run build:devtools-chrome");
|
|
if (chromeResult !== 0) {
|
|
logError("Build devtools chrome failed. Aborting.");
|
|
return;
|
|
}
|
|
await execCommand("mv dist/devtools dist/devtools-chrome");
|
|
const firefoxResult = await execCommand("npm run build:devtools-firefox");
|
|
if (firefoxResult !== 0) {
|
|
logError("Build devtools firefox failed. Aborting.");
|
|
return;
|
|
}
|
|
await execCommand("mv dist/devtools dist/devtools-firefox");
|
|
await execCommand("cd dist && zip -r owl-devtools.zip devtools-chrome devtools-firefox && cd ..");
|
|
await execCommand("rm -r dist/devtools-chrome dist/devtools-firefox && rm dist/compiler.js");
|
|
|
|
// ---------------------------------------------------------------------------
|
|
log(`Step ${step++}/${STEPS}: updating owl on github page...`);
|
|
await fs.copyFileSync("dist/owl.es.js", "docs/owl.js");
|
|
|
|
// ---------------------------------------------------------------------------
|
|
log(`Step ${step++}/${STEPS}: creating git commit...`);
|
|
const escapedContent = content.replace(/\"/g, '\\\"').replace(/\`/g, '\\\`');
|
|
const gitResult = await execCommand(`git commit -am "[REL] v${next}\n\n${escapedContent}"`);
|
|
if (gitResult !== 0) {
|
|
logError("Git commit failed. Aborting.");
|
|
return;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
log(`Step ${step++}/${STEPS}: pushing on github...`);
|
|
const pushResult = await execCommand("git push origin " + branch);
|
|
if (pushResult !== 0) {
|
|
logError("git push failed. Aborting.");
|
|
return;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
log(`Step ${step++}/${STEPS}: Creating the release...`);
|
|
const relaseResult = await execCommand(`gh release create v${next} dist/*.js dist/*.zip ${draft} -F ${file}`);
|
|
if (relaseResult !== 0) {
|
|
logError("github release failed. Aborting.");
|
|
return;
|
|
}
|
|
|
|
log(`Step ${step++}/${STEPS}: publishing module on npm...`);
|
|
await execCommand("npm publish");
|
|
|
|
log("Owl Release process completed! Thank you for your patience");
|
|
await execCommand(`gh release view`);
|
|
await execCommand(`gh release view -w`);
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Helpers
|
|
// -----------------------------------------------------------------------------
|
|
|
|
function log(text) {
|
|
console.log(chalk.yellow(formatLog(text)));
|
|
}
|
|
|
|
function logError(text) {
|
|
console.log(chalk.red(formatLog(text)));
|
|
}
|
|
|
|
function formatLog(text) {
|
|
return `[REL] ${text}`;
|
|
}
|
|
|
|
function logSubContent(text) {
|
|
for (let line of text.split("\n")) {
|
|
if (line.trim()) {
|
|
console.log(" " + line);
|
|
}
|
|
}
|
|
}
|
|
|
|
function ask(question) {
|
|
return new Promise(resolve => {
|
|
rl.question(question, result => {
|
|
resolve(result);
|
|
});
|
|
});
|
|
}
|
|
|
|
function logStream(stream) {
|
|
stream.on("data", data => {
|
|
logSubContent(data);
|
|
});
|
|
}
|
|
|
|
function execCommand(command) {
|
|
return new Promise(resolve => {
|
|
const childProcess = exec(command, (err, stdout, stderr) => {
|
|
if (err) {
|
|
resolve(err.code);
|
|
}
|
|
});
|
|
childProcess.on("exit", code => {
|
|
resolve(code);
|
|
});
|
|
logStream(childProcess.stdout);
|
|
logStream(childProcess.stderr);
|
|
});
|
|
}
|
|
|
|
function readFile(file) {
|
|
return new Promise((resolve, reject) => {
|
|
fs.readFile(file, "utf8", function(err, content) {
|
|
if (err) {
|
|
reject(err);
|
|
} else {
|
|
resolve(content);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
function writeFile(file, content) {
|
|
return new Promise((resolve, reject) => {
|
|
fs.writeFile(file, content, "utf8", err => {
|
|
if (err) {
|
|
reject(err);
|
|
} else {
|
|
resolve();
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
async function getOutput(command) {
|
|
return new Promise((resolve, reject) => {
|
|
const childProcess = exec(command, (err, stdout, stderr) => {
|
|
if (err) {
|
|
reject(err);
|
|
}
|
|
resolve(stdout);
|
|
});
|
|
childProcess.on("exit", code => {
|
|
if (code !== 0) {
|
|
reject(code);
|
|
}
|
|
});
|
|
});
|
|
}
|