Skip to content
Merged
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
5 changes: 4 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,8 @@
},
"rules": {
"no-param-reassign": [ "warn", { "props": true }]
}
},
"parserOptions": {
"ecmaVersion": "2020"
}
}
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@
"jest": {
"collectCoverage": true,
"collectCoverageFrom": [
"src/**/*.js"
"src/**/*.js",
"!src/types.jsdoc.js"
],
"coverageThreshold": {
"global": {
Expand Down
29 changes: 23 additions & 6 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const globby = require('globby')
const path = require('path')
const archiver = require('archiver')
// this is a static list that comes from here: https://developer.adobe.com/runtime/docs/guides/reference/runtimes/
const SupportedRuntimes = ['nodejs:10', 'nodejs:12', 'nodejs:14', 'nodejs:16', 'nodejs:18']
const SupportedRuntimes = ['sequence', 'nodejs:10', 'nodejs:12', 'nodejs:14', 'nodejs:16', 'nodejs:18']
const DEFAULT_PACKAGE_RESERVED_NAME = 'default'

/**
Expand Down Expand Up @@ -1491,11 +1491,14 @@ async function deployPackage (entities, ow, logger, imsOrgId) {

for (const action of entities.actions) {
const retAction = cloneDeep(action)
try {
validateActionRuntime(retAction)
} catch (e) {
const supportedServerRuntimes = await getSupportedServerRuntimes(apihost)
throw new Error(`${e.message}. Supported runtimes on ${apihost}: ${supportedServerRuntimes}`)
if (retAction?.exec?.kind && !isSupportedActionKind(retAction)) {
const supportedServerRuntimes = (await getSupportedServerRuntimes(apihost)).sort().reverse()
if (supportedServerRuntimes.includes(retAction?.exec?.kind)) {
aioLogger.debug(`Local node kinds mismatch with server supported kinds ${supportedServerRuntimes}`)
} else {
throw new Error(`Unsupported node version '${retAction?.exec?.kind}' in action ${retAction.name}.\n` +
`Supported runtimes on ${apihost}: ${supportedServerRuntimes}`)
}
}

if (retAction.exec && action.exec.kind === 'sequence') {
Expand Down Expand Up @@ -2017,18 +2020,31 @@ function replacePackagePlaceHolder (config) {
* Checks the validity of nodejs version in action definition and throws an error if invalid.
*
* @param {object} action action object
* @deprecated Use isSupportedActionKind instead
*/
function validateActionRuntime (action) {
// I suspect we have an issue here with 2 kinds of kinds ...
// sometimes this method is called with 'sequence' which is a different kind of kind than exec.kind which
// comes from action: runtime: in manifest -jm
// it would be nice if we didn't throw an excption when we could just return a boolean, otherwise the caller
// has to wrap this in a try/catch block -jm
if (action.exec && action.exec.kind && action.exec.kind.toLowerCase().startsWith('nodejs:')) {
if (!SupportedRuntimes.includes(action.exec.kind)) {
throw new Error(`Unsupported node version '${action.exec.kind}' in action ${action.name}. Supported versions are ${SupportedRuntimes}`)
}
}
}

/**
* Checks the validity of nodejs version in action definition returns true if valid.
*
* @param {object} action action object
* @returns {boolean} true if action kind is supported
*/
function isSupportedActionKind (action) {
return SupportedRuntimes.includes(action?.exec?.kind?.toLowerCase())
}

/**
* Returns the action's build file name without the .zip extension
*
Expand Down Expand Up @@ -2186,5 +2202,6 @@ module.exports = {
dumpActionsBuiltInfo,
actionBuiltBefore,
safeParse,
isSupportedActionKind,
DEFAULT_PACKAGE_RESERVED_NAME
}
53 changes: 46 additions & 7 deletions test/utils.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -765,12 +765,41 @@ describe('deployPackage', () => {
json: () => result
})

const supportedClientRuntimes = ['nodejs:10', 'nodejs:12', 'nodejs:14', 'nodejs:16', 'nodejs:18']
const supportedServerRuntimes = await utils.getSupportedServerRuntimes(initOptions.apihost)
await expect(() =>
utils.deployPackage(JSON.parse(fs.readFileSync('/basic_manifest_unsupported_kind.json')), ow, mockLogger, imsOrgId)
).rejects.toThrow(/Unsupported node version 'nodejs:8/)
})

test('basic manifest - local `kind` list missing', async () => {
const imsOrgId = 'MyIMSOrgId'
const mockLogger = jest.fn()
const actionOptions = {
apiKey: 'my-key',
namespace: 'my-namespace'
}
const initOptions = {
apihost: 'https://adobeio.adobeioruntime.net'
}
ow.mockResolvedProperty('actions.client.options', actionOptions)
ow.mockResolvedProperty(owInitOptions, initOptions)

const result = {
runtimes: {
nodejs: [
{ kind: 'nodejs:8' }, // server says it supports nodejs:8!
{ kind: 'nodejs:16' }
]
}
}
mockFetch.mockResolvedValue({
ok: true,
status: 200,
json: () => result
})

await expect(() =>
utils.deployPackage(JSON.parse(fs.readFileSync('/basic_manifest_unsupported_kind.json')), ow, mockLogger, imsOrgId)
).rejects.toThrow(`Unsupported node version 'nodejs:8' in action hello/helloAction. Supported versions are ${supportedClientRuntimes}. Supported runtimes on ${initOptions.apihost}: ${supportedServerRuntimes}`)
).not.toThrow()
})

test('basic manifest (fetch error)', async () => {
Expand Down Expand Up @@ -2243,10 +2272,20 @@ describe('validateActionRuntime', () => {
expect(() => utils.validateActionRuntime({ exec: { kind: 'nodejs:16' } })).not.toThrow()
expect(() => utils.validateActionRuntime({ exec: { kind: 'nodejs:18' } })).not.toThrow()
})

test('invalid nodejs version', async () => {
const func = () => utils.validateActionRuntime({ exec: { kind: 'nodejs:17' } })
expect(func).toThrowError('Unsupported node version')
test('no exec', () => {
expect(utils.validateActionRuntime({})).toBeUndefined()
})
test('no runtime kind', () => {
expect(utils.validateActionRuntime({ exec: {} })).toBeUndefined()
})
test('valid runtime kind', () => {
expect(utils.validateActionRuntime({ exec: { kind: 'nodejs:14' } })).toBeUndefined()
})
test('valid runtime kind - toLower', () => {
expect(() => utils.validateActionRuntime({ exec: { kind: 'NODEJS:14' } })).toThrowError('Unsupported node version')
})
test('invalid nodejs version', () => {
expect(() => utils.validateActionRuntime({ exec: { kind: 'nodejs:17' } })).toThrowError('Unsupported node version')
})

test('dumpActionsBuiltInfo might catch some errors under unlikely conditions', async () => {
Expand Down