mirror of
https://github.com/bluxmit/alnoda-workspaces.git
synced 2024-09-19 03:07:10 +12:00
256 lines
7.6 KiB
JavaScript
256 lines
7.6 KiB
JavaScript
|
// Cronicle Auto Installer
|
||
|
// Copyright (c) 2015 - 2019 Joseph Huckaby, MIT License.
|
||
|
// https://github.com/jhuckaby/Cronicle
|
||
|
|
||
|
// To install, issue this command as root:
|
||
|
// curl -s "https://raw.githubusercontent.com/jhuckaby/Cronicle/master/bin/install.js" | node
|
||
|
|
||
|
var path = require('path');
|
||
|
var fs = require('fs');
|
||
|
var util = require('util');
|
||
|
var os = require('os');
|
||
|
var cp = require('child_process');
|
||
|
|
||
|
var installer_version = '1.3';
|
||
|
var base_dir = '/opt/cronicle';
|
||
|
var log_dir = base_dir + '/logs';
|
||
|
var log_file = '';
|
||
|
var gh_repo_url = 'http://github.com/jhuckaby/Cronicle';
|
||
|
var gh_releases_url = 'https://api.github.com/repos/jhuckaby/Cronicle/releases';
|
||
|
var gh_head_tarball_url = 'https://github.com/jhuckaby/Cronicle/archive/master.tar.gz';
|
||
|
|
||
|
// don't allow npm to delete these (ugh)
|
||
|
var packages_to_check = ['couchbase', 'aws-sdk', 'redis'];
|
||
|
var packages_to_rescue = {};
|
||
|
|
||
|
var restore_packages = function() {
|
||
|
// restore packages that npm killed during upgrade
|
||
|
var cmd = "npm install";
|
||
|
for (var pkg in packages_to_rescue) {
|
||
|
cmd += ' ' + pkg + '@' + packages_to_rescue[pkg];
|
||
|
}
|
||
|
if (log_file) {
|
||
|
fs.appendFileSync(log_file, "\nExecuting npm command to restore lost packages: " + cmd + "\n");
|
||
|
cmd += ' >>' + log_file + ' 2>&1';
|
||
|
}
|
||
|
cp.execSync(cmd);
|
||
|
};
|
||
|
|
||
|
var print = function(msg) {
|
||
|
process.stdout.write(msg);
|
||
|
if (log_file) fs.appendFileSync(log_file, msg);
|
||
|
};
|
||
|
var warn = function(msg) {
|
||
|
process.stderr.write(msg);
|
||
|
if (log_file) fs.appendFileSync(log_file, msg);
|
||
|
};
|
||
|
var die = function(msg) {
|
||
|
warn( "\nERROR: " + msg.trim() + "\n\n" );
|
||
|
process.exit(1);
|
||
|
};
|
||
|
var logonly = function(msg) {
|
||
|
if (log_file) fs.appendFileSync(log_file, msg);
|
||
|
};
|
||
|
|
||
|
if (process.getuid() != 0) {
|
||
|
die( "The Cronicle auto-installer must be run as root." );
|
||
|
}
|
||
|
|
||
|
// create base and log directories
|
||
|
try { cp.execSync( "mkdir -p " + base_dir + " && chmod 775 " + base_dir ); }
|
||
|
catch (err) { die("Failed to create base directory: " + base_dir + ": " + err); }
|
||
|
|
||
|
try { cp.execSync( "mkdir -p " + log_dir + " && chmod 777 " + log_dir ); }
|
||
|
catch (err) { die("Failed to create log directory: " + log_dir + ": " + err); }
|
||
|
|
||
|
// start logging from this point onward
|
||
|
log_file = log_dir + '/install.log';
|
||
|
logonly( "\nStarting install run: " + (new Date()).toString() + "\n" );
|
||
|
|
||
|
print(
|
||
|
"\nCronicle Installer v" + installer_version + "\n" +
|
||
|
"Copyright (c) 2015 - 2018 PixlCore.com. MIT Licensed.\n" +
|
||
|
"Log File: " + log_file + "\n\n"
|
||
|
);
|
||
|
|
||
|
process.chdir( base_dir );
|
||
|
|
||
|
var is_preinstalled = false;
|
||
|
var cur_version = '';
|
||
|
var new_version = process.argv[2] || '';
|
||
|
|
||
|
try {
|
||
|
var stats = fs.statSync( base_dir + '/package.json' );
|
||
|
var json = require( base_dir + '/package.json' );
|
||
|
if (json && json.version) {
|
||
|
cur_version = json.version;
|
||
|
is_preinstalled = true;
|
||
|
}
|
||
|
}
|
||
|
catch (err) {;}
|
||
|
|
||
|
var is_running = false;
|
||
|
if (is_preinstalled) {
|
||
|
var pid_file = log_dir + '/cronicled.pid';
|
||
|
try {
|
||
|
var pid = fs.readFileSync(pid_file, { encoding: 'utf8' });
|
||
|
is_running = process.kill( pid, 0 );
|
||
|
}
|
||
|
catch (err) {;}
|
||
|
}
|
||
|
|
||
|
print( "Fetching release list...\n");
|
||
|
logonly( "Releases URL: " + gh_releases_url + "\n" );
|
||
|
|
||
|
cp.exec('curl -s ' + gh_releases_url, function (err, stdout, stderr) {
|
||
|
if (err) {
|
||
|
print( stdout.toString() );
|
||
|
warn( stderr.toString() );
|
||
|
die("Failed to fetch release list: " + gh_releases_url + ": " + err);
|
||
|
}
|
||
|
|
||
|
var releases = null;
|
||
|
try { releases = JSON.parse( stdout.toString() ); }
|
||
|
catch (err) {
|
||
|
die("Failed to parse JSON from GitHub: " + gh_releases_url + ": " + err);
|
||
|
}
|
||
|
|
||
|
// util.isArray is DEPRECATED??? Nooooooooode!
|
||
|
var isArray = Array.isArray || util.isArray;
|
||
|
if (!isArray(releases)) die("Unexpected response from GitHub Releases API: " + gh_releases_url + ": Not an array");
|
||
|
|
||
|
var release = null;
|
||
|
for (var idx = 0, len = releases.length; idx < len; idx++) {
|
||
|
var rel = releases[idx];
|
||
|
var ver = rel.tag_name.replace(/^\D+/, '');
|
||
|
rel.version = ver;
|
||
|
|
||
|
if (!new_version || (ver == new_version)) {
|
||
|
release = rel;
|
||
|
new_version = ver;
|
||
|
idx = len;
|
||
|
}
|
||
|
} // foreach release
|
||
|
|
||
|
if (!release) {
|
||
|
// no release found -- use HEAD rev?
|
||
|
if (!new_version || new_version.match(/HEAD/i)) {
|
||
|
release = {
|
||
|
version: 'HEAD',
|
||
|
tarball_url: gh_head_tarball_url
|
||
|
};
|
||
|
}
|
||
|
else {
|
||
|
die("Release not found: " + new_version);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// sanity check
|
||
|
if (is_preinstalled && (cur_version == new_version)) {
|
||
|
if (process.argv[2]) print( "\nVersion " + cur_version + " is already installed.\n\n" );
|
||
|
else print( "\nVersion " + cur_version + " is already installed, and is the latest.\n\n" );
|
||
|
process.exit(0);
|
||
|
}
|
||
|
|
||
|
// proceed with installation
|
||
|
if (is_preinstalled) print("Upgrading Cronicle from v"+cur_version+" to v"+new_version+"...\n");
|
||
|
else print("Installing Cronicle v"+new_version+"...\n");
|
||
|
|
||
|
if (is_running) {
|
||
|
print("\n");
|
||
|
try { cp.execSync( base_dir + "/bin/control.sh stop", { stdio: 'inherit' } ); }
|
||
|
catch (err) { die("Failed to stop Cronicle: " + err); }
|
||
|
print("\n");
|
||
|
}
|
||
|
|
||
|
// download tarball and expand into current directory
|
||
|
var tarball_url = release.tarball_url;
|
||
|
logonly( "Tarball URL: " + tarball_url + "\n" );
|
||
|
|
||
|
cp.exec('curl -L ' + tarball_url + ' | tar zxf - --strip-components 1', function (err, stdout, stderr) {
|
||
|
if (err) {
|
||
|
print( stdout.toString() );
|
||
|
warn( stderr.toString() );
|
||
|
die("Failed to download release: " + tarball_url + ": " + err);
|
||
|
}
|
||
|
else {
|
||
|
logonly( stdout.toString() + stderr.toString() );
|
||
|
}
|
||
|
|
||
|
try {
|
||
|
var stats = fs.statSync( base_dir + '/package.json' );
|
||
|
var json = require( base_dir + '/package.json' );
|
||
|
}
|
||
|
catch (err) {
|
||
|
die("Failed to download package: " + tarball_url + ": " + err);
|
||
|
}
|
||
|
|
||
|
print( is_preinstalled ? "Updating dependencies...\n" : "Installing dependencies...\n");
|
||
|
|
||
|
var npm_cmd = is_preinstalled ? "npm update --unsafe-perm" : "npm install --unsafe-perm";
|
||
|
logonly( "Executing command: " + npm_cmd + "\n" );
|
||
|
|
||
|
// temporarily stash add-on modules that were installed separately (thanks npm)
|
||
|
if (is_preinstalled) packages_to_check.forEach( function(pkg) {
|
||
|
if (fs.existsSync('node_modules/' + pkg)) {
|
||
|
packages_to_rescue[pkg] = JSON.parse( fs.readFileSync('node_modules/' + pkg + '/package.json', 'utf8') ).version;
|
||
|
}
|
||
|
});
|
||
|
|
||
|
// install dependencies via npm
|
||
|
cp.exec(npm_cmd, function (err, stdout, stderr) {
|
||
|
if (err) {
|
||
|
print( stdout.toString() );
|
||
|
warn( stderr.toString() );
|
||
|
if (is_preinstalled) restore_packages();
|
||
|
die("Failed to install dependencies: " + err);
|
||
|
}
|
||
|
else {
|
||
|
logonly( stdout.toString() + stderr.toString() );
|
||
|
}
|
||
|
|
||
|
print("Running post-install script...\n");
|
||
|
logonly( "Executing command: node bin/build.js dist\n" );
|
||
|
|
||
|
// finally, run postinstall script
|
||
|
cp.exec('node bin/build.js dist', function (err, stdout, stderr) {
|
||
|
if (is_preinstalled) {
|
||
|
// for upgrades only print output on error
|
||
|
if (err) {
|
||
|
print( stdout.toString() );
|
||
|
warn( stderr.toString() );
|
||
|
if (is_preinstalled) restore_packages();
|
||
|
die("Failed to run post-install: " + err);
|
||
|
}
|
||
|
else {
|
||
|
if (is_preinstalled) restore_packages();
|
||
|
print("Upgrade complete.\n\n");
|
||
|
|
||
|
if (is_running) {
|
||
|
try { cp.execSync( base_dir + "/bin/control.sh start", { stdio: 'inherit' } ); }
|
||
|
catch (err) { die("Failed to start Cronicle: " + err); }
|
||
|
print("\n");
|
||
|
}
|
||
|
}
|
||
|
} // upgrade
|
||
|
else {
|
||
|
// first time install, always print output
|
||
|
print( stdout.toString() );
|
||
|
warn( stderr.toString() );
|
||
|
|
||
|
if (err) {
|
||
|
die("Failed to run post-install: " + err);
|
||
|
}
|
||
|
else {
|
||
|
print("Installation complete.\n\n");
|
||
|
}
|
||
|
} // first install
|
||
|
|
||
|
logonly( "Completed install run: " + (new Date()).toString() + "\n" );
|
||
|
|
||
|
process.exit(0);
|
||
|
} ); // build.js
|
||
|
} ); // npm
|
||
|
} ); // download
|
||
|
} ); // releases api
|