DuckieTV
DuckieTV copied to clipboard
Implement auto-upgrade service for standalone
For a different project that uses nwjs i've built an angular module that fetches a .tgz from an internal gitlab server, extracts it, and overwrites the files in the current directory.
For this to work for DuckieTV there's some todos:
- [x] disable usage of packing sources zip file into duckietv binary for linux
- [x] disable usage of packing sources zip file into duckietv binary for osx
- [ ] disable usage of packing sources zip file into duckietv binary for windows
- [ ] add node_modules requirements to package.json, clean it up a bit
- [ ] add node_modules to dist
- [ ] have the nightly build a zipfile that hosts just the build, not the binaries
- [ ] implement something like this w.i.p. module:
/**
* Compares latest release on github to the one stored in settings.
* If older:
* - downloads new version full tarbal to temp dir
* - extracts temp tarbal
* - overwrites contents of current install with updated install
* - temp dir cleanup on process exit.
*/
DuckieTV.factory("UpdateService", ["SettingsService", "GithubService", "$q", "$http", function(SettingsService, GithubService, $q, $http) {
const TARGET_FILE = 'download.tgz';
/**
* Update check stores last known release here. Will be set to current release when upgrade is complete.
*/
var lastKnownCommit = null;
/**
* Convert a browser ArrayBuffer to nodejs Buffer.
* Needed because $http performs the request to fetch this update, it only gives arraybuffers
* for binary data. Nodejs (that does the unpacking) requires a Buffer to write to disk.
*/
function toBuffer(ab) {
var buf = new Buffer(ab.byteLength);
var view = new Uint8Array(ab);
for (var i = 0; i < buf.length; ++i) { buf[i] = view[i]; }
return buf;
}
var service = {
status: 'idle',
/**
* Fetch latest release from github
*/
check: function() {
service.status = 'fetching latest commit';
var currentCommit = SettingsService.get('currentcommit.hash');
return GithubService.getLastRelease('SchizoDuckie/DuckieTV').then(function(commitHash) {
lastKnownCommit = commitHash;
return commitHash != currentCommit;
});
},
/**
* Check if an upgrade is needed and execute it.
* Stores hash of last kown commit in settings
* @return Promise(bool upgraded)
*/
upgradeIfNeeded: function() {
service.status = 'checking for update';
return service.check().then(function(upgradeNeeded) {
if (upgradeNeeded) {
return service.downloadAndUpgrade().then(function() {
SettingsService.set('currentcommit.hash', lastKnownCommit);
return true;
})
} else {
return false;
service.status = 'no update needed';
}
});
},
/**
* Perform download and upgrade
* @return Promise(result msg)
*/
downloadAndUpgrade: function() {
service.status = 'downloading';
return $http.get(DOWNLOAD_URL, { responseType: "arraybuffer" }).then(function(result) {
service.status = 'saving';
var tarball = require('tarball-extract'),
ncp = require('ncp').ncp,
temp = require('temp'),
path = require('path'),
fs = require('fs');
temp.track(); // auto-cleanup the mess
return $q(function(resolve, reject) {
temp.mkdir('discipline', function(err, dirPath) {
var tempPath = path.join(dirPath),
download = path.join(tempPath, TARGET_FILE);
var writeStream = fs.createWriteStream(download, {
flags: 'w',
encoding: 'binary'
});
writeStream.on('close', function() {
service.status = 'extracting';
tarball.extractTarball(download, tempPath, function(err, result) {
service.status = 'installing';
ncp(path.join(dirPath, 'discipline.git'), '.', {}, function(err) {
if(err) {
console.error('error copying!', err);
service.status = 'failure';
reject(err);
} else {
service.status = 'cleaning up';
}
temp.cleanup(function(err, stats) {
console.log("upgrade complete!", stats, err);
service.status = 'upgrade complete';
resolve("installed version "+lastKnownCommit);
});
});
});
})
writeStream.write(toBuffer(result.data));
writeStream.end();
});
});
});
}
}
return service;
}]);
For the upcoming 1.1.4 release i want to at least implement the first three parts of this since the build scripts need to be updated for nw.js 0.18.* anyway