mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[ADD] tooling: add release script
More work is needed to complete this, but the basics is here, and it is difficult to test. closes #612
This commit is contained in:
+3
-1
@@ -23,4 +23,6 @@ package-lock.json
|
|||||||
node_modules
|
node_modules
|
||||||
|
|
||||||
# Extras temp file
|
# Extras temp file
|
||||||
/tools/owl.js
|
/tools/owl.js
|
||||||
|
|
||||||
|
release-notes.md
|
||||||
+8
-2
@@ -4,7 +4,10 @@
|
|||||||
"description": "Odoo Web Library (OWL)",
|
"description": "Odoo Web Library (OWL)",
|
||||||
"main": "dist/owl.js",
|
"main": "dist/owl.js",
|
||||||
"types": "dist/types/index.d.ts",
|
"types": "dist/types/index.d.ts",
|
||||||
"files": ["dist/types/", "dist/owl.js"],
|
"files": [
|
||||||
|
"dist/types/",
|
||||||
|
"dist/owl.js"
|
||||||
|
],
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=10.15.3"
|
"node": ">=10.15.3"
|
||||||
},
|
},
|
||||||
@@ -21,7 +24,8 @@
|
|||||||
"pretools:watch": "npm run build",
|
"pretools:watch": "npm run build",
|
||||||
"tools:watch": "npm-run-all --parallel tools:serve \"build:* -- --watch\"",
|
"tools:watch": "npm-run-all --parallel tools:serve \"build:* -- --watch\"",
|
||||||
"prettier": "prettier {src/*.ts,src/**/*.ts,tests/*.ts,tests/**/*.ts,doc/*.md,doc/**/*.md} --write",
|
"prettier": "prettier {src/*.ts,src/**/*.ts,tests/*.ts,tests/**/*.ts,doc/*.md,doc/**/*.md} --write",
|
||||||
"publish": "npm run buildcommonjs && npm publish"
|
"publish": "npm run buildcommonjs && npm publish",
|
||||||
|
"release": "node tools/release.js"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@@ -36,8 +40,10 @@
|
|||||||
"dependencies": {},
|
"dependencies": {},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/jest": "^23.3.12",
|
"@types/jest": "^23.3.12",
|
||||||
|
"chalk": "^3.0.0",
|
||||||
"cpx": "^1.5.0",
|
"cpx": "^1.5.0",
|
||||||
"git-rev-sync": "^1.12.0",
|
"git-rev-sync": "^1.12.0",
|
||||||
|
"github-api": "^3.3.0",
|
||||||
"jest": "^23.6.0",
|
"jest": "^23.6.0",
|
||||||
"jest-environment-jsdom": "^24.7.1",
|
"jest-environment-jsdom": "^24.7.1",
|
||||||
"live-server": "^1.2.1",
|
"live-server": "^1.2.1",
|
||||||
|
|||||||
@@ -0,0 +1,215 @@
|
|||||||
|
const package = require("../package.json");
|
||||||
|
const readline = require("readline");
|
||||||
|
const fs = require("fs");
|
||||||
|
const exec = require("child_process").exec;
|
||||||
|
const chalk = require("chalk");
|
||||||
|
const GitHub = require("github-api");
|
||||||
|
|
||||||
|
const REL_NOTES_FILE = `release-notes.md`;
|
||||||
|
const STEPS = 10;
|
||||||
|
|
||||||
|
const rl = readline.createInterface({
|
||||||
|
input: process.stdin,
|
||||||
|
output: process.stdout
|
||||||
|
});
|
||||||
|
|
||||||
|
startRelease().then(() => {
|
||||||
|
rl.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// Relase Script
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
async function startRelease() {
|
||||||
|
log(`*** Owl release script ***`);
|
||||||
|
log(`Current Version: ${package.version}`);
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
log(`Step 1/${STEPS}: collecting info...`);
|
||||||
|
const current = package.version;
|
||||||
|
const next = await ask("Next version: ");
|
||||||
|
let file = await ask(`Release notes (${REL_NOTES_FILE}): `);
|
||||||
|
file = file || REL_NOTES_FILE;
|
||||||
|
let content;
|
||||||
|
try {
|
||||||
|
content = await readFile("./" + file);
|
||||||
|
} catch (e) {
|
||||||
|
logSubContent(e.message);
|
||||||
|
log("Cannot find release notes... Aborting");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Todo: add playground update feature
|
||||||
|
// let shouldUpdateStr = await ask("Update Playground? (y/n)");
|
||||||
|
// const shouldUpdatePlayground = shouldUpdateStr === "y";
|
||||||
|
const token = await ask("Github token: ");
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
log(`Step 2/${STEPS}: running tests...`);
|
||||||
|
const testsResult = await execCommand("npm run test");
|
||||||
|
if (testsResult !== 0) {
|
||||||
|
log("Test suite does not pass. Aborting.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ask("Ready for next step...");
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
log(`Step 3/${STEPS}: updating package.json, readme.md and roadmap.md...`);
|
||||||
|
await replaceInFile("./package.json", current, next);
|
||||||
|
await replaceInFile("./README.md", current, next);
|
||||||
|
await replaceInFile("./roadmap.md", current, next);
|
||||||
|
ask("Ready for next step...");
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
log(`Step 4/${STEPS}: creating git commit...`);
|
||||||
|
const gitResult = await execCommand(`git commit -am "[REL] v${next}\n\n${content}"`);
|
||||||
|
if (gitResult !== 0) {
|
||||||
|
log("Git commit failed. Aborting.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ask("Ready for next step...");
|
||||||
|
|
||||||
|
// -------------------j--------------------------------------------------------
|
||||||
|
log(`Step 5/${STEPS}: building owl (iife version)...`);
|
||||||
|
const buildResult = await execCommand("npm run build");
|
||||||
|
if (buildResult !== 0) {
|
||||||
|
log("Build failed. Aborting.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ask("Ready for next step...");
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
log(`Step 6/${STEPS}: minifying owl...`);
|
||||||
|
const minifyResult = await execCommand("npm run minify");
|
||||||
|
if (minifyResult !== 0) {
|
||||||
|
log("Minify failed. Aborting.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ask("Ready for next step...");
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
log(`Step 7/${STEPS}: pushing on github...`);
|
||||||
|
const pushResult = await execCommand("git push");
|
||||||
|
if (pushResult !== 0) {
|
||||||
|
log("git push failed. Aborting.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ask("Ready for next step...");
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
log(`Step 8/${STEPS}: publishing release notes on github...`);
|
||||||
|
const options = {
|
||||||
|
tag_name: `v${next}`,
|
||||||
|
name: `v${next}`,
|
||||||
|
body: content,
|
||||||
|
draft: true // todo: remove this someday
|
||||||
|
};
|
||||||
|
const result = await createRelease(token, options);
|
||||||
|
console.log(result);
|
||||||
|
ask("Ready for next step...");
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
log(`Step 9/${STEPS}: adding assets to release...`);
|
||||||
|
await ask("Please add owl.js and owl.min.js to draft release, then confirm");
|
||||||
|
// todo: do this with curl
|
||||||
|
// curl \
|
||||||
|
// -H "Authorization: token $GITHUB_TOKEN" \
|
||||||
|
// -H "Content-Type: $(file -b --mime-type $FILE)" \
|
||||||
|
// --data-binary @$FILE \
|
||||||
|
// "https://uploads.github.com/repos/hubot/singularity/releases/123/assets?name=$(basename $FILE)"
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
log(`Step 10/${STEPS}: publishing module on npm...`);
|
||||||
|
await execCommand("npm run publish");
|
||||||
|
|
||||||
|
log("Owl Release process completed! Thank you for your patience");
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// Helpers
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function log(text) {
|
||||||
|
console.log(chalk.yellow(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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function replaceInFile(file, from, to) {
|
||||||
|
const content = await readFile(file);
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const updatedContent = content.replace(new RegExp(from, "g"), to);
|
||||||
|
fs.writeFile(file, updatedContent, "utf8", err => {
|
||||||
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
} else {
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function createRelease(token, options) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
var gh = new GitHub({ token });
|
||||||
|
gh.getRepo("odoo", "owl").createRelease(options, (err, result, req) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
} else {
|
||||||
|
resolve(result);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user