mirror of
https://github.com/balena-io/etcher.git
synced 2025-07-29 14:16:36 +00:00
refactor(GUI): make use of etcher-latest-version
(#544)
The code that performs an HTTP request to the S3 bucket where released are stored and determines which is the latest available version was extracted to a separate module called `etcher-latest-version`, mainly for the website to be able to re-use this functionality. See: https://github.com/resin-io-modules/etcher-latest-version Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>
This commit is contained in:
parent
f277724749
commit
c434746a49
@ -1,70 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2016 Resin.io
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const _ = require('lodash');
|
|
||||||
const semver = require('semver');
|
|
||||||
const xml = require('xml2js');
|
|
||||||
|
|
||||||
module.exports = function($q, $http, UPDATE_NOTIFIER_URL) {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @summary Get the latest published Etcher version
|
|
||||||
* @function
|
|
||||||
* @public
|
|
||||||
*
|
|
||||||
* @description
|
|
||||||
* This function performs its job by querying the publicily accessible
|
|
||||||
* S3 bucket where we store the builds and uses the `node-semver` module
|
|
||||||
* to determine which is the latest one.
|
|
||||||
*
|
|
||||||
* @fulfil {String} - latest version
|
|
||||||
* @returns {Promise}
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* UpdateNotifierS3Service.getLatestVersion().then((latestVersion) => {
|
|
||||||
* console.log('The latest version is: ' + latestVersion);
|
|
||||||
* });
|
|
||||||
*/
|
|
||||||
this.getLatestVersion = () => {
|
|
||||||
return $http.get(UPDATE_NOTIFIER_URL).then((response) => {
|
|
||||||
return $q((resolve, reject) => {
|
|
||||||
xml.parseString(response.data, (error, result) => {
|
|
||||||
if (error) {
|
|
||||||
return reject(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
const bucketEntries = result.ListBucketResult.Contents;
|
|
||||||
return resolve(_.reduce(bucketEntries, (latest, entry) => {
|
|
||||||
const version = _.chain(entry.Key)
|
|
||||||
.first()
|
|
||||||
.split('/')
|
|
||||||
.nth(1)
|
|
||||||
.value();
|
|
||||||
|
|
||||||
return semver.gt(version, latest) ? version : latest;
|
|
||||||
|
|
||||||
// This is a good accumulator default value since
|
|
||||||
// every version is semantically greater than this.
|
|
||||||
}, '0.0.0'));
|
|
||||||
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
|
@ -17,8 +17,40 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const semver = require('semver');
|
const semver = require('semver');
|
||||||
|
const etcherLatestVersion = require('etcher-latest-version');
|
||||||
|
|
||||||
module.exports = function($uibModal, UPDATE_NOTIFIER_SLEEP_TIME, ManifestBindService, UpdateNotifierS3Service, SettingsModel) {
|
module.exports = function($uibModal, $http, $q, UPDATE_NOTIFIER_SLEEP_TIME, ManifestBindService, SettingsModel) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Get the latest available Etcher version
|
||||||
|
* @function
|
||||||
|
* @private
|
||||||
|
*
|
||||||
|
* @fulfil {String} - latest version
|
||||||
|
* @returns {Promise}
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* UpdateNotifierService.getLatestVersion().then((latestVersion) => {
|
||||||
|
* console.log(`The latest version is: ${latestVersion}`);
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
this.getLatestVersion = () => {
|
||||||
|
return $q((resolve, reject) => {
|
||||||
|
return etcherLatestVersion((url, callback) => {
|
||||||
|
return $http.get(url).then((response) => {
|
||||||
|
return callback(null, response.data);
|
||||||
|
}).catch((error) => {
|
||||||
|
return callback(error);
|
||||||
|
});
|
||||||
|
}, (error, latestVersion) => {
|
||||||
|
if (error) {
|
||||||
|
return reject(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return resolve(latestVersion);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @summary Check if the current version is the latest version
|
* @summary Check if the current version is the latest version
|
||||||
@ -36,7 +68,7 @@ module.exports = function($uibModal, UPDATE_NOTIFIER_SLEEP_TIME, ManifestBindSer
|
|||||||
* });
|
* });
|
||||||
*/
|
*/
|
||||||
this.isLatestVersion = () => {
|
this.isLatestVersion = () => {
|
||||||
return UpdateNotifierS3Service.getLatestVersion().then((version) => {
|
return this.getLatestVersion().then((version) => {
|
||||||
return semver.gte(ManifestBindService.get('version'), version);
|
return semver.gte(ManifestBindService.get('version'), version);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -29,10 +29,8 @@ const UpdateNotifier = angular.module(MODULE_NAME, [
|
|||||||
require('../../os/open-external/open-external')
|
require('../../os/open-external/open-external')
|
||||||
]);
|
]);
|
||||||
|
|
||||||
UpdateNotifier.constant('UPDATE_NOTIFIER_URL', 'https://resin-production-downloads.s3.amazonaws.com');
|
|
||||||
UpdateNotifier.constant('UPDATE_NOTIFIER_SLEEP_TIME', 7 * 24 * 60 * 60 * 100);
|
UpdateNotifier.constant('UPDATE_NOTIFIER_SLEEP_TIME', 7 * 24 * 60 * 60 * 100);
|
||||||
UpdateNotifier.controller('UpdateNotifierController', require('./controllers/update-notifier'));
|
UpdateNotifier.controller('UpdateNotifierController', require('./controllers/update-notifier'));
|
||||||
UpdateNotifier.service('UpdateNotifierService', require('./services/update-notifier'));
|
UpdateNotifier.service('UpdateNotifierService', require('./services/update-notifier'));
|
||||||
UpdateNotifier.service('UpdateNotifierS3Service', require('./services/update-notifier-s3'));
|
|
||||||
|
|
||||||
module.exports = MODULE_NAME;
|
module.exports = MODULE_NAME;
|
||||||
|
12
npm-shrinkwrap.json
generated
12
npm-shrinkwrap.json
generated
@ -1551,6 +1551,18 @@
|
|||||||
"from": "etcher-image-write@>=5.0.2 <6.0.0",
|
"from": "etcher-image-write@>=5.0.2 <6.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/etcher-image-write/-/etcher-image-write-5.0.2.tgz"
|
"resolved": "https://registry.npmjs.org/etcher-image-write/-/etcher-image-write-5.0.2.tgz"
|
||||||
},
|
},
|
||||||
|
"etcher-latest-version": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"from": "etcher-latest-version@latest",
|
||||||
|
"resolved": "https://registry.npmjs.org/etcher-latest-version/-/etcher-latest-version-1.0.0.tgz",
|
||||||
|
"dependencies": {
|
||||||
|
"semver": {
|
||||||
|
"version": "5.2.0",
|
||||||
|
"from": "semver@>=5.2.0 <6.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-5.2.0.tgz"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"event-emitter": {
|
"event-emitter": {
|
||||||
"version": "0.3.4",
|
"version": "0.3.4",
|
||||||
"from": "event-emitter@>=0.3.4 <0.4.0",
|
"from": "event-emitter@>=0.3.4 <0.4.0",
|
||||||
|
@ -69,6 +69,7 @@
|
|||||||
"electron-is-running-in-asar": "^1.0.0",
|
"electron-is-running-in-asar": "^1.0.0",
|
||||||
"etcher-image-stream": "^2.2.0",
|
"etcher-image-stream": "^2.2.0",
|
||||||
"etcher-image-write": "^5.0.2",
|
"etcher-image-write": "^5.0.2",
|
||||||
|
"etcher-latest-version": "^1.0.0",
|
||||||
"file-tail": "^0.3.0",
|
"file-tail": "^0.3.0",
|
||||||
"flexboxgrid": "^6.3.0",
|
"flexboxgrid": "^6.3.0",
|
||||||
"immutable": "^3.8.1",
|
"immutable": "^3.8.1",
|
||||||
@ -87,7 +88,6 @@
|
|||||||
"trackjs": "^2.1.16",
|
"trackjs": "^2.1.16",
|
||||||
"umount": "^1.1.3",
|
"umount": "^1.1.3",
|
||||||
"username": "^2.1.0",
|
"username": "^2.1.0",
|
||||||
"xml2js": "^0.4.16",
|
|
||||||
"yargs": "^4.6.0"
|
"yargs": "^4.6.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -101,16 +101,6 @@ describe('Browser: UpdateNotifier', function() {
|
|||||||
let UpdateNotifierService;
|
let UpdateNotifierService;
|
||||||
let ManifestBindService;
|
let ManifestBindService;
|
||||||
|
|
||||||
beforeEach(function() {
|
|
||||||
angular.mock.module(function($provide) {
|
|
||||||
$provide.value('UpdateNotifierS3Service', {
|
|
||||||
getLatestVersion: function() {
|
|
||||||
return $q.resolve(ManifestBindService.get('version'));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(angular.mock.inject(function(_$q_, _$rootScope_, _UpdateNotifierService_, _ManifestBindService_) {
|
beforeEach(angular.mock.inject(function(_$q_, _$rootScope_, _UpdateNotifierService_, _ManifestBindService_) {
|
||||||
$q = _$q_;
|
$q = _$q_;
|
||||||
$rootScope = _$rootScope_;
|
$rootScope = _$rootScope_;
|
||||||
@ -118,6 +108,15 @@ describe('Browser: UpdateNotifier', function() {
|
|||||||
ManifestBindService = _ManifestBindService_;
|
ManifestBindService = _ManifestBindService_;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
this.getLatestVersionStub = m.sinon.stub(UpdateNotifierService, 'getLatestVersion');
|
||||||
|
this.getLatestVersionStub.returns($q.resolve(ManifestBindService.get('version')));
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
this.getLatestVersionStub.restore();
|
||||||
|
});
|
||||||
|
|
||||||
it('should resolve true', function() {
|
it('should resolve true', function() {
|
||||||
let result = null;
|
let result = null;
|
||||||
|
|
||||||
@ -137,22 +136,21 @@ describe('Browser: UpdateNotifier', function() {
|
|||||||
let $rootScope;
|
let $rootScope;
|
||||||
let UpdateNotifierService;
|
let UpdateNotifierService;
|
||||||
|
|
||||||
beforeEach(function() {
|
|
||||||
angular.mock.module(function($provide) {
|
|
||||||
$provide.value('UpdateNotifierS3Service', {
|
|
||||||
getLatestVersion: function() {
|
|
||||||
return $q.resolve('99999.9.9');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(angular.mock.inject(function(_$q_, _$rootScope_, _UpdateNotifierService_) {
|
beforeEach(angular.mock.inject(function(_$q_, _$rootScope_, _UpdateNotifierService_) {
|
||||||
$q = _$q_;
|
$q = _$q_;
|
||||||
$rootScope = _$rootScope_;
|
$rootScope = _$rootScope_;
|
||||||
UpdateNotifierService = _UpdateNotifierService_;
|
UpdateNotifierService = _UpdateNotifierService_;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
this.getLatestVersionStub = m.sinon.stub(UpdateNotifierService, 'getLatestVersion');
|
||||||
|
this.getLatestVersionStub.returns($q.resolve('99999.9.9'));
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
this.getLatestVersionStub.restore();
|
||||||
|
});
|
||||||
|
|
||||||
it('should resolve false', function() {
|
it('should resolve false', function() {
|
||||||
let result = null;
|
let result = null;
|
||||||
|
|
||||||
@ -172,22 +170,21 @@ describe('Browser: UpdateNotifier', function() {
|
|||||||
let $rootScope;
|
let $rootScope;
|
||||||
let UpdateNotifierService;
|
let UpdateNotifierService;
|
||||||
|
|
||||||
beforeEach(function() {
|
|
||||||
angular.mock.module(function($provide) {
|
|
||||||
$provide.value('UpdateNotifierS3Service', {
|
|
||||||
getLatestVersion: function() {
|
|
||||||
return $q.resolve('0.0.0');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(angular.mock.inject(function(_$q_, _$rootScope_, _UpdateNotifierService_) {
|
beforeEach(angular.mock.inject(function(_$q_, _$rootScope_, _UpdateNotifierService_) {
|
||||||
$q = _$q_;
|
$q = _$q_;
|
||||||
$rootScope = _$rootScope_;
|
$rootScope = _$rootScope_;
|
||||||
UpdateNotifierService = _UpdateNotifierService_;
|
UpdateNotifierService = _UpdateNotifierService_;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
this.getLatestVersionStub = m.sinon.stub(UpdateNotifierService, 'getLatestVersion');
|
||||||
|
this.getLatestVersionStub.returns($q.resolve('0.0.0'));
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
this.getLatestVersionStub.restore();
|
||||||
|
});
|
||||||
|
|
||||||
it('should resolve true', function() {
|
it('should resolve true', function() {
|
||||||
let result = null;
|
let result = null;
|
||||||
|
|
||||||
@ -205,120 +202,4 @@ describe('Browser: UpdateNotifier', function() {
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('UpdateNotifierS3Service', function() {
|
|
||||||
|
|
||||||
let UpdateNotifierS3Service;
|
|
||||||
let $rootScope;
|
|
||||||
|
|
||||||
beforeEach(angular.mock.inject(function(_$rootScope_, _UpdateNotifierS3Service_) {
|
|
||||||
$rootScope = _$rootScope_;
|
|
||||||
UpdateNotifierS3Service = _UpdateNotifierS3Service_;
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('given a mocked S3 XML response', function() {
|
|
||||||
|
|
||||||
let $httpBackend;
|
|
||||||
let UPDATE_NOTIFIER_URL;
|
|
||||||
|
|
||||||
beforeEach(angular.mock.inject(function($injector) {
|
|
||||||
$httpBackend = $injector.get('$httpBackend');
|
|
||||||
UPDATE_NOTIFIER_URL = $injector.get('UPDATE_NOTIFIER_URL');
|
|
||||||
|
|
||||||
$httpBackend.whenGET(UPDATE_NOTIFIER_URL).respond(`
|
|
||||||
<ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
|
|
||||||
<Name>resin-production-downloads</Name>
|
|
||||||
<Prefix/>
|
|
||||||
<Marker/>
|
|
||||||
<MaxKeys>1000</MaxKeys>
|
|
||||||
<IsTruncated>false</IsTruncated>
|
|
||||||
<Contents>
|
|
||||||
<Key>etcher/1.0.0-beta.0/Etcher-darwin-x64.dmg</Key>
|
|
||||||
<LastModified>2016-03-10T17:34:21.000Z</LastModified>
|
|
||||||
<ETag>"5a715255aa25686688bf1e23bc1d3fc6"</ETag>
|
|
||||||
<Size>46109720</Size>
|
|
||||||
<StorageClass>STANDARD</StorageClass>
|
|
||||||
</Contents>
|
|
||||||
<Contents>
|
|
||||||
<Key>etcher/1.0.0-beta.1/Etcher-darwin-x64.dmg</Key>
|
|
||||||
<LastModified>2016-04-08T20:12:03.000Z</LastModified>
|
|
||||||
<ETag>"cc1d6d9d53385e3edd099416fcd894c1"</ETag>
|
|
||||||
<Size>47071474</Size>
|
|
||||||
<StorageClass>STANDARD</StorageClass>
|
|
||||||
</Contents>
|
|
||||||
<Contents>
|
|
||||||
<Key>etcher/1.0.0-beta.2/Etcher-darwin-x64.dmg</Key>
|
|
||||||
<LastModified>2016-04-08T19:03:18.000Z</LastModified>
|
|
||||||
<ETag>"5f1849f7781197ce2ee6129c16bcd498"</ETag>
|
|
||||||
<Size>48650090</Size>
|
|
||||||
<StorageClass>STANDARD</StorageClass>
|
|
||||||
</Contents>
|
|
||||||
<Contents>
|
|
||||||
<Key>etcher/1.0.0-beta.3/Etcher-darwin-x64.dmg</Key>
|
|
||||||
<LastModified>2016-04-18T01:32:09.000Z</LastModified>
|
|
||||||
<ETag>"c173895886f44d115c66e7206ce3dff8"</ETag>
|
|
||||||
<Size>50585335</Size>
|
|
||||||
<StorageClass>STANDARD</StorageClass>
|
|
||||||
</Contents>
|
|
||||||
<Contents>
|
|
||||||
<Key>etcher/1.0.0-beta.3/Etcher-darwin-x64.zip</Key>
|
|
||||||
<LastModified>2016-04-18T01:42:37.000Z</LastModified>
|
|
||||||
<ETag>"e9f6e957e65373b232530215d98df141"</ETag>
|
|
||||||
<Size>129327442</Size>
|
|
||||||
<StorageClass>STANDARD</StorageClass>
|
|
||||||
</Contents>
|
|
||||||
<Contents>
|
|
||||||
<Key>etcher/1.0.0-beta.4/Etcher-darwin-x64.dmg</Key>
|
|
||||||
<LastModified>2016-04-22T17:29:49.000Z</LastModified>
|
|
||||||
<ETag>"bccb0024c58747a9b7516cbdfc5a7ecb"</ETag>
|
|
||||||
<Size>55240852</Size>
|
|
||||||
<StorageClass>STANDARD</StorageClass>
|
|
||||||
</Contents>
|
|
||||||
<Contents>
|
|
||||||
<Key>etcher/1.0.0-beta.4/Etcher-darwin-x64.zip</Key>
|
|
||||||
<LastModified>2016-04-22T17:43:27.000Z</LastModified>
|
|
||||||
<ETag>"c93e26e68b3c4f2b7e8e88e6befc8e64"</ETag>
|
|
||||||
<Size>135443284</Size>
|
|
||||||
<StorageClass>STANDARD</StorageClass>
|
|
||||||
</Contents>
|
|
||||||
<Contents>
|
|
||||||
<Key>etcher/1.0.0-beta.5/Etcher-darwin-x64.dmg</Key>
|
|
||||||
<LastModified>2016-05-04T08:27:11.000Z</LastModified>
|
|
||||||
<ETag>"fb596bfdb8bbaf09807b5fc4a940ce14"</ETag>
|
|
||||||
<Size>77757305</Size>
|
|
||||||
<StorageClass>STANDARD</StorageClass>
|
|
||||||
</Contents>
|
|
||||||
<Contents>
|
|
||||||
<Key>etcher/1.0.0-beta.5/Etcher-darwin-x64.zip</Key>
|
|
||||||
<LastModified>2016-05-04T08:39:56.000Z</LastModified>
|
|
||||||
<ETag>"3f11c1b6f06644f9ceb2aea4b1947fdf"</ETag>
|
|
||||||
<Size>157933876</Size>
|
|
||||||
<StorageClass>STANDARD</StorageClass>
|
|
||||||
</Contents>
|
|
||||||
</ListBucketResult>
|
|
||||||
`);
|
|
||||||
}));
|
|
||||||
|
|
||||||
afterEach(function() {
|
|
||||||
$httpBackend.verifyNoOutstandingExpectation();
|
|
||||||
$httpBackend.verifyNoOutstandingRequest();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should resolve the latest version', function() {
|
|
||||||
$httpBackend.expectGET(UPDATE_NOTIFIER_URL);
|
|
||||||
|
|
||||||
let latestVersion = null;
|
|
||||||
UpdateNotifierS3Service.getLatestVersion().then(function(result) {
|
|
||||||
latestVersion = result;
|
|
||||||
});
|
|
||||||
|
|
||||||
$rootScope.$apply();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
m.chai.expect(latestVersion).to.equal('1.0.0-beta.5');
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user