Skip to content

Commit

Permalink
feature: fetch metadata for latest server version
Browse files Browse the repository at this point in the history
  • Loading branch information
tkurki committed Apr 25, 2021
1 parent 4fdd292 commit 8ea37cf
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 56 deletions.
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', () =>
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

0 comments on commit 8ea37cf

Please sign in to comment.