-
Notifications
You must be signed in to change notification settings - Fork 4
SED-4581 Modernize Node.js Agent #612
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
base: master
Are you sure you want to change the base?
Changes from all commits
3c9ead0
1a76f3a
38f8fb9
d563c0f
a12119c
0afb116
cd4efbb
4ed4fdc
eda0ee6
a5bdc4a
ed1404c
23815bf
8a6a87e
8b68411
706dba3
fe0038e
f12d0ec
81c4041
4e607c6
d4e78ae
c05b688
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,6 @@ | ||
| node_modules/ | ||
| .npm | ||
| !/bin | ||
| filemanager/work/ | ||
| filemanager/work/ | ||
| /coverage/ | ||
| /npm-project-workspaces/ |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,117 @@ | ||||||
| /* | ||||||
| * Copyright (C) 2026, exense GmbH | ||||||
| * | ||||||
| * This file is part of Step | ||||||
| * | ||||||
| * Step is free software: you can redistribute it and/or modify | ||||||
| * it under the terms of the GNU Affero General Public License as published by | ||||||
| * the Free Software Foundation, either version 3 of the License, or | ||||||
| * (at your option) any later version. | ||||||
| * | ||||||
| * Step is distributed in the hope that it will be useful, | ||||||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||||
| * GNU Affero General Public License for more details. | ||||||
| * | ||||||
| * You should have received a copy of the GNU Affero General Public License | ||||||
| * along with Step. If not, see <http://www.gnu.org/licenses/>. | ||||||
| */ | ||||||
|
|
||||||
| const { OutputBuilder } = require("./output"); | ||||||
| const Session = require("./session"); | ||||||
| const fs = require("fs"); | ||||||
| const path = require('path') | ||||||
| const session = new Session(); | ||||||
|
|
||||||
| process.on('message', async ({ type, projectPath, functionName, input, properties, keywordDirectory }) => { | ||||||
| if (type === 'KEYWORD') { | ||||||
| console.log("[Agent fork] Calling keyword " + functionName) | ||||||
jeromecomte marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
| const outputBuilder = new OutputBuilder(); | ||||||
| try { | ||||||
| if (!keywordDirectoryExists(projectPath, keywordDirectory)) { | ||||||
| outputBuilder.fail("The keyword directory '" + keywordDirectory + "' doesn't exist in " + path.basename(projectPath) + ". Possible cause: If using TypeScript, the keywords may not have been compiled. Fix: Ensure your project is built before deploying to Step or during 'npm install'.") | ||||||
| } else { | ||||||
| const kwModules = await importAllKeywords(projectPath, keywordDirectory); | ||||||
| let keywordSearchResult = searchKeyword(kwModules, functionName); | ||||||
| if (!keywordSearchResult) { | ||||||
| console.log('[Agent fork] Unable to find Keyword ' + functionName + "'"); | ||||||
jeromecomte marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
| outputBuilder.fail("Unable to find Keyword '" + functionName + "'"); | ||||||
| } else { | ||||||
| const module = keywordSearchResult.keywordModule; | ||||||
| const keyword = keywordSearchResult.keywordFunction; | ||||||
|
|
||||||
| try { | ||||||
| const beforeKeyword = module['beforeKeyword']; | ||||||
| if(beforeKeyword) { | ||||||
| await beforeKeyword(functionName); | ||||||
| } | ||||||
| await keyword(input, outputBuilder, session, properties); | ||||||
| } catch (e) { | ||||||
| const onError = module['onError']; | ||||||
| if (onError) { | ||||||
| if (await onError(e, input, outputBuilder, session, properties)) { | ||||||
| console.log('[Agent fork] Keyword execution failed and onError hook returned \'true\'') | ||||||
jeromecomte marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
| outputBuilder.fail(e) | ||||||
| } else { | ||||||
| console.log('[Agent fork] Keyword execution failed and onError hook returned \'false\'') | ||||||
jeromecomte marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
| } | ||||||
| } else { | ||||||
| console.log('[Agent fork] Keyword execution failed. No onError hook defined') | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Direct
Suggested change
|
||||||
| outputBuilder.fail(e) | ||||||
| } | ||||||
| } finally { | ||||||
| let afterKeyword = module['afterKeyword']; | ||||||
| if (afterKeyword) { | ||||||
| await afterKeyword(functionName); | ||||||
| } | ||||||
| } | ||||||
| } | ||||||
| } | ||||||
| } finally { | ||||||
| console.log("[Agent fork] Returning output") | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||
| process.send(outputBuilder.build()); | ||||||
| } | ||||||
| } else if (type === 'KILL') { | ||||||
| console.log("[Agent fork] Exiting...") | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||
| await session.asyncDispose(); | ||||||
| process.exit(1) | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||
| } | ||||||
|
|
||||||
| function keywordDirectoryExists(projectPath, keywordDirectory) { | ||||||
| return fs.existsSync(path.resolve(projectPath, keywordDirectory)) | ||||||
| } | ||||||
|
|
||||||
| async function importAllKeywords(projectPath, keywordDirectory) { | ||||||
| const kwModules = []; | ||||||
| const kwDir = path.resolve(projectPath, keywordDirectory); | ||||||
| console.log("[Agent fork] Searching keywords in: " + kwDir) | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Direct
Suggested change
|
||||||
| const kwFiles = fs.readdirSync(kwDir); | ||||||
| for (const kwFile of kwFiles) { | ||||||
| if (kwFile.endsWith('.js')) { | ||||||
| let kwModule = "file://" + path.resolve(kwDir, kwFile); | ||||||
| console.log("[Agent fork] Importing keywords from module: " + kwModule) | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Direct
Suggested change
|
||||||
| let module = await import(kwModule); | ||||||
| kwModules.push(module); | ||||||
| } | ||||||
| } | ||||||
| return kwModules; | ||||||
| } | ||||||
|
|
||||||
| function searchKeyword(kwModules, keywordName) { | ||||||
| const kwModule = kwModules.find(m => m[keywordName]); | ||||||
| return kwModule ? {keywordFunction: kwModule[keywordName], keywordModule: kwModule} : undefined; | ||||||
| } | ||||||
| }); | ||||||
|
|
||||||
| process.on('unhandledRejection', error => { | ||||||
| console.log('[Agent fork] Critical: an unhandled error (unhandled promise rejection) occurred and might not have been reported', error) | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Direct
Suggested change
|
||||||
| }) | ||||||
|
|
||||||
| process.on('uncaughtException', error => { | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Direct logger.error('[Agent fork] Critical: an unhandled error (uncaught exception) occurred and might not have been reported', error) |
||||||
| console.log('[Agent fork] Critical: an unhandled error (uncaught exception) occurred and might not have been reported', error) | ||||||
| }) | ||||||
|
|
||||||
| process.on('SIGTERM', () => { | ||||||
| console.log("[Agent fork] Received SIGTERM. Exiting...") | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||
| process.exit(1); | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||
| }); | ||||||
Uh oh!
There was an error while loading. Please reload this page.