Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] feature: implement check for minimum node version for next server version #1135

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions src/interfaces/appstore.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const { installModule, removeModule } = require('../modules')
const {
isTheServerModule,
findModulesWithKeyword,
getLatestServerVersion,
getLatestServerVersionInfo,
getAuthor,
getKeywords
} = require('../modules')
Expand Down Expand Up @@ -125,9 +125,9 @@ module.exports = function(app) {
app.get(`${SERVERROUTESPREFIX}/appstore/available/`, (req, res) => {
findPluginsAndWebapps()
.then(([plugins, webapps]) => {
getLatestServerVersion(app.config.version)
.then(serverVersion => {
const result = getAllModuleInfo(plugins, webapps, serverVersion)
getLatestServerVersionInfo(app.config.version)
.then(({ version }) => {
const result = getAllModuleInfo(plugins, webapps, version)
res.send(JSON.stringify(result))
})
.catch(err => {
Expand Down Expand Up @@ -189,7 +189,8 @@ module.exports = function(app) {
installing: [],
categories: getAvailableCategories(),
storeAvailable: true,
isInDocker: process.env.IS_IN_DOCKER === 'true'
isInDocker: process.env.IS_IN_DOCKER === 'true',
nodeVersion: {}
}
}

Expand Down
103 changes: 64 additions & 39 deletions src/modules.test.js → src/modules.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
const chai = require('chai')
const _ = require('lodash')
const fs = require('fs')
const path = require('path')
const {
modulesWithKeyword,
import chai from 'chai'
import fs from 'fs'
import _ from 'lodash'
import path from 'path'
import {
checkForNewServerVersion,
getLatestServerVersion
} = require('./modules')
getLatestServerVersionInfo,
modulesWithKeyword
} from './modules'

describe('modulesWithKeyword', () => {
it('returns a list of modules with one "installed" update in config dir', () => {
Expand All @@ -26,6 +26,7 @@ describe('modulesWithKeyword', () => {

const app = {
config: {
name: 'dummy-name-in-test',
appPath: path.join(__dirname + '/../'),
configPath: testTempDir
}
Expand Down Expand Up @@ -61,127 +62,151 @@ describe('modulesWithKeyword', () => {
})

describe('checkForNewServerVersion', () => {
const newMinorVersionInfo = {
version: '1.18.0',
disttag: 'latest',
minimumNodeVersion: '10'
}
it('normal version upgrade', done => {
checkForNewServerVersion(
'1.17.0',
(err, newVersion) => {
if (err) {
done(err)
} else {
chai.expect(newVersion).to.equal('1.18.0')
chai.expect(newVersion).to.equal(newMinorVersionInfo.version)
done()
}
},
() => Promise.resolve('1.18.0')
() => Promise.resolve(newMinorVersionInfo)
)
})

it('normal version does not upgrade to beta', done => {
const newBetaVersion = {
version: '1.18.0-beta.2',
disttag: 'latest',
minimumNodeVersion: '10'
}
checkForNewServerVersion(
'1.17.0',
err => {
done('callback should not be called')
},
() => Promise.resolve('1.18.0-beta.1')
() => Promise.resolve(newBetaVersion)
)
done()
})

it('beta upgrades to same minor newer beta', done => {
const newerBetaVersionInfo = {
version: '1.18.0-beta.2',
disttag: 'latest',
minimumNodeVersion: '10'
}
checkForNewServerVersion(
'1.18.0-beta.1',
(err, newVersion) => {
if (err) {
done(err)
} else {
chai.expect(newVersion).to.equal('1.18.0-beta.2')
chai.expect(newVersion).to.equal(newerBetaVersionInfo.version)
done()
}
},
() => Promise.resolve('1.18.0-beta.2')
() => Promise.resolve(newerBetaVersionInfo)
)
})

it('beta upgrades to same normal version', done => {
const sameNormalVersion = {
version: '1.18.0',
disttag: 'latest',
minimumNodeVersion: '10'
}
checkForNewServerVersion(
'1.18.0-beta.2',
(err, newVersion) => {
if (err) {
done(err)
} else {
chai.expect(newVersion).to.equal('1.18.0')
chai.expect(newVersion).to.equal(sameNormalVersion.version)
done()
}
},
() => Promise.resolve('1.18.0')
() => Promise.resolve(sameNormalVersion)
)
})

it('beta upgrades to newer normal version', done => {
const newerNormalVersion = {
version: '1.19.0',
disttag: 'latest',
minimumNodeVersion: '10'
}
checkForNewServerVersion(
'1.18.0-beta.2',
(err, newVersion) => {
if (err) {
done(err)
} else {
chai.expect(newVersion).to.equal('1.19.0')
chai.expect(newVersion).to.equal(newerNormalVersion.version)
done()
}
},
() => Promise.resolve('1.19.0')
() => Promise.resolve(newerNormalVersion)
)
})

it('beta does not upgrade to newer minor beta', done => {
const nextMinorBetaVersion = {
version: '1.18.0-beta.2',
disttag: 'latest',
minimumNodeVersion: '10'
}
checkForNewServerVersion(
'1.17.0-beta.1',
err => {
done('callback should not be called')
},
() => Promise.resolve('1.18.0-beta.2')
() => Promise.resolve(nextMinorBetaVersion)
)
done()
})
})

describe('getLatestServerVersion', () => {
it('latest for normal is normal', () => {
return getLatestServerVersion('1.17.0', () =>
return getLatestServerVersionInfo('1.17.0', () =>
Promise.resolve({
json: () => ({
latest: '1.18.3',
beta: '1.19.0-beta.1'
})
latest: '1.18.0',
beta: '1.19.0-beta.1'
})
).then(newVersion => {
chai.expect(newVersion).to.equal('1.18.3')
).then(newVersionInfo => {
chai.expect(newVersionInfo.version).to.equal('1.18.0')
})
})

it('latest for beta is newer same series beta', done => {
getLatestServerVersion('1.18.0-beta.2', () =>
return getLatestServerVersionInfo('1.18.0-beta.2', () =>
Promise.resolve({
json: () => ({
latest: '1.17.3',
beta: '1.18.0-beta.3'
})
latest: '1.17.3',
beta: '1.18.0-beta.3'
})
).then(newVersion => {
chai.expect(newVersion).to.equal('1.18.0-beta.3')
).then(newVersionInfo => {
chai.expect(newVersionInfo.version).to.equal('1.18.0-beta.3')
done()
})
})

it('latest for beta is newer real release', () => {
return getLatestServerVersion('1.18.0-beta.2', () =>
return getLatestServerVersionInfo('1.18.0-beta.2', () =>
Promise.resolve({
json: () => ({
latest: '1.18.0',
beta: '1.18.0-beta.3'
})
latest: '1.18.0',
beta: '1.18.0-beta.3'
})
).then(newVersion => {
chai.expect(newVersion).to.equal('1.18.0')
).then(newVersionInfo => {
chai.expect(newVersionInfo.version).to.equal('1.18.0')
})
})
})
49 changes: 37 additions & 12 deletions src/modules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ const priorityPrefix = (a: ModuleData, b: ModuleData) =>
getModuleSortName(a).localeCompare(getModuleSortName(b))

// Searches for installed modules that contain `keyword`.
function modulesWithKeyword(app: App, keyword: string) {
export function modulesWithKeyword(app: App, keyword: string) {
return _.uniqBy(
// _.flatten since values are inside an array. [[modules...], [modules...]]
_.flatten(
Expand Down Expand Up @@ -265,44 +265,69 @@ function findModulesWithKeyword(keyword: string) {
}

function doFetchDistTags() {
return fetch('http://registry.npmjs.org/-/package/signalk-server/dist-tags')
return fetch(
'http://registry.npmjs.org/-/package/signalk-server/dist-tags'
).then(r => r.json())
}

function getLatestServerVersion(
export interface ServerVersionInfo {
version: string
disttag: string
minimumNodeVersion: string
}

export function getLatestServerVersionInfo(
currentVersion: string,
distTags = doFetchDistTags
): Promise<string> {
): Promise<ServerVersionInfo> {
return new Promise((resolve, reject) => {
distTags()
.then(npmjsResults => npmjsResults.json())
.then(npmjsParsed => {
const prereleaseData = semver.prerelease(currentVersion)
if (prereleaseData) {
if (semver.satisfies(npmjsParsed.latest, `>${currentVersion}`)) {
resolve(npmjsParsed.latest)
return [npmjsParsed.latest, 'latest']
} else {
resolve(npmjsParsed[prereleaseData[0]])
return [npmjsParsed[prereleaseData[0]], 'beta']
}
} else {
resolve(npmjsParsed.latest)
return [npmjsParsed.latest, 'latest']
}
})
.then(([version, disttag]) => {
return fetch('https://registry.npmjs.org/signalk-server', {
headers: {
Accept: 'application/vnd.npm.install-v1+json'
}
})
.then(res => res.json())
.then(json => {
return json
})
.then(moduleMetadata => {
resolve({
version,
disttag,
minimumNodeVersion: `${moduleMetadata.versions[version].engines}`
})
})
})
.catch(reject)
})
}

function checkForNewServerVersion(
export function checkForNewServerVersion(
currentVersion: string,
serverUpgradeIsAvailable: (
errMessage: string | void,
version?: string
) => any,
getLatestServerVersionP: (
version: string
) => Promise<string> = getLatestServerVersion
) => Promise<ServerVersionInfo> = getLatestServerVersionInfo
) {
getLatestServerVersionP(currentVersion)
.then((version: string) => {
.then(({ version }) => {
if (semver.satisfies(new SemVer(version), `>${currentVersion}`)) {
serverUpgradeIsAvailable(undefined, version)
}
Expand Down Expand Up @@ -342,7 +367,7 @@ module.exports = {
removeModule,
isTheServerModule,
findModulesWithKeyword,
getLatestServerVersion,
getLatestServerVersionInfo,
checkForNewServerVersion,
getAuthor,
getKeywords,
Expand Down