luci-app-attendedsysupgrade: support revision checks

SNAPSHOTS are not real releases and therefore the app always offers an
upgrade, even if running the latest build. To prevent that all SNAPSHOTS
now check for the running revision and if a newer one is available.

Also do a bunch of refactoring based on JavaScript I learned over the
last week.

Signed-off-by: Paul Spooren <mail@aparcar.org>
This commit is contained in:
Paul Spooren 2021-08-29 00:37:31 -10:00
parent ab2f8b8b04
commit f799d550b6

View file

@ -33,6 +33,26 @@ function get_branch(version) {
return version.replace("-SNAPSHOT", "").split(".").slice(0, 2).join("."); return version.replace("-SNAPSHOT", "").split(".").slice(0, 2).join(".");
} }
function get_revision_count(revision) {
return parseInt(revision.substring(1).split("-")[0])
}
function error_api_connect(response) {
console.log(response)
ui.showModal(_('Error connecting to upgrade server'), [
E('p', {}, _(`Could not reach API at "${response.url}. Please try again later.`)),
E('pre', {}, response.responseText),
E('div', {
'class': 'right'
}, [
E('div', {
'class': 'btn',
'click': ui.hideModal
}, _('Close'))
])
]);
}
function install_sysupgrade(url, keep, sha256) { function install_sysupgrade(url, keep, sha256) {
displayStatus("notice spinning", E('p', _('Downloading firmware from server to browser'))); displayStatus("notice spinning", E('p', _('Downloading firmware from server to browser')));
request.get(url, { request.get(url, {
@ -49,7 +69,7 @@ function install_sysupgrade(url, keep, sha256) {
form_data.append("filedata", response.blob()); form_data.append("filedata", response.blob());
displayStatus("notice spinning", E('p', _('Uploading firmware from browser to device'))); displayStatus("notice spinning", E('p', _('Uploading firmware from browser to device')));
request.get(L.env.cgi_base + "/cgi-upload", { request.get(`${L.env.cgi_base}/cgi-upload`, {
method: 'PUT', method: 'PUT',
content: form_data content: form_data
}) })
@ -82,9 +102,9 @@ function request_sysupgrade(server_url, data) {
var res, req; var res, req;
if (data.request_hash) { if (data.request_hash) {
req = request.get(server_url + "/api/build/" + data.request_hash) req = request.get(`${server_url}/api/v1/build/${data.request_hash}`)
} else { } else {
req = request.post(server_url + "/api/build", { req = request.post(`${server_url}/api/v1/build`, {
profile: data.board_name, profile: data.board_name,
target: data.target, target: data.target,
version: data.version, version: data.version,
@ -96,7 +116,7 @@ function request_sysupgrade(server_url, data) {
req.then(response => { req.then(response => {
switch (response.status) { switch (response.status) {
case 200: case 200:
var res = response.json() res = response.json()
var image; var image;
for (image of res.images) { for (image of res.images) {
if (image.type == "sysupgrade") { if (image.type == "sysupgrade") {
@ -104,7 +124,7 @@ function request_sysupgrade(server_url, data) {
} }
} }
if (image.name != undefined) { if (image.name != undefined) {
var sysupgrade_url = server_url + "/store/" + res.bin_dir + "/" + image.name; var sysupgrade_url = `${server_url}/store/${res.bin_dir}/${image.name}`;
var keep = E('input', { var keep = E('input', {
type: 'checkbox' type: 'checkbox'
@ -112,7 +132,7 @@ function request_sysupgrade(server_url, data) {
keep.checked = true; keep.checked = true;
var fields = [ var fields = [
_('Version'), res.version_number + ' ' + res.version_code, _('Version'), `${res.version_number} ${res.version_code}`,
_('File'), E('a', { _('File'), E('a', {
'href': sysupgrade_url 'href': sysupgrade_url
}, image.name), }, image.name),
@ -220,41 +240,68 @@ function request_sysupgrade(server_url, data) {
}); });
} }
function check_sysupgrade(server_url, current_version, target, board_name, packages) { async function check_sysupgrade(server_url, system_board, packages) {
displayStatus("notice spinning", E('p', _('Searching for an available sysupgrade'))); var {
var current_branch = get_branch(current_version); board_name
} = system_board;
var {
target,
version,
revision
} = system_board.release;
var current_branch = get_branch(version);
var advanced_mode = uci.get_first('attendedsysupgrade', 'client', 'advanced_mode') || 0; var advanced_mode = uci.get_first('attendedsysupgrade', 'client', 'advanced_mode') || 0;
var candidates = []; var candidates = [];
var response;
request.get(server_url + "/json/latest.json", { displayStatus("notice spinning", E('p', _(`Searching for an available sysupgrade of ${version} - ${revision}`)));
timeout: 8000
}) if (version.endsWith("SNAPSHOT")) {
.then(response => response.json()) response = await request.get(`${server_url}/api/v1/revision/${version}/${target}`)
.then(response => { if (!response.ok) {
if (current_version == "SNAPSHOT") { error_api_connect(response);
candidates.push("SNAPSHOT"); return;
}
const remote_revision = response.json().revision;
if (get_revision_count(revision) < get_revision_count(remote_revision)) {
candidates.push(version);
}
} else { } else {
for (let version of response["latest"]) { response = await request.get(`${server_url}/api/overview`, {
var branch = get_branch(version); timeout: 8000
});
if (!response.ok) {
error_api_connect(response);
return;
}
const latest = response.json().latest
for (let remote_version of latest) {
var remote_branch = get_branch(remote_version);
// already latest version installed // already latest version installed
if (current_version == version) { if (version == remote_version) {
break; break;
} }
// skip branch upgrades outside the advanced mode // skip branch upgrades outside the advanced mode
if (current_branch != branch && advanced_mode == 0) { if (current_branch != remote_branch && advanced_mode == 0) {
continue; continue;
} }
candidates.unshift(version); candidates.unshift(remote_version);
// don't offer branches older than the current // don't offer branches older than the current
if (current_branch == branch) { if (current_branch == remote_branch) {
break; break;
} }
} }
} }
if (candidates.length) { if (candidates.length) {
var m, s, o; var m, s, o;
@ -309,7 +356,7 @@ function check_sysupgrade(server_url, current_version, target, board_name, packa
}); });
} else { } else {
ui.showModal(_('No upgrade available'), [ ui.showModal(_('No upgrade available'), [
E('p', {}, _("The device runs the latest firmware version")), E('p', {}, _(`The device runs the latest firmware version ${version} - ${revision}`)),
E('div', { E('div', {
'class': 'right' 'class': 'right'
}, [ }, [
@ -320,21 +367,6 @@ function check_sysupgrade(server_url, current_version, target, board_name, packa
]) ])
]); ]);
} }
})
.catch(error => {
ui.showModal(_('Error connecting to upgrade server'), [
E('p', {}, _('Could not reach API at "%s". Please try again later.'.format(server_url))),
E('pre', {}, error),
E('div', {
'class': 'right'
}, [
E('div', {
'class': 'btn',
'click': ui.hideModal
}, _('Close'))
])
]);
});
} }
function displayStatus(type, content) { function displayStatus(type, content) {
@ -361,9 +393,7 @@ return view.extend({
}, },
render: function(res) { render: function(res) {
var packages = res[0].packages; var packages = res[0].packages;
var current_version = res[1].release.version; var system_board = res[1];
var target = res[1].release.target;
var board_name = res[1].board_name;
var auto_search = uci.get_first('attendedsysupgrade', 'client', 'auto_search') || 1; var auto_search = uci.get_first('attendedsysupgrade', 'client', 'auto_search') || 1;
var server_url = uci.get_first('attendedsysupgrade', 'server', 'url'); var server_url = uci.get_first('attendedsysupgrade', 'server', 'url');
@ -374,13 +404,13 @@ return view.extend({
]; ];
if (auto_search == 1) { if (auto_search == 1) {
check_sysupgrade(server_url, current_version, target, board_name, packages) check_sysupgrade(server_url, system_board, packages)
} }
view.push(E('p', { view.push(E('p', {
'class': 'btn cbi-button-positive', 'class': 'btn cbi-button-positive',
'click': function() { 'click': function() {
check_sysupgrade(server_url, current_version, target, board_name, packages) check_sysupgrade(server_url, system_board, packages)
} }
}, _('Search for sysupgrade'))); }, _('Search for sysupgrade')));