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

Feat nodejs: Added Nodejs Conversion #248

Merged
merged 4 commits into from
Nov 26, 2024
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
3 changes: 3 additions & 0 deletions convert/jenkinsjson/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,9 @@ func collectStepsWithID(currentNode jenkinsjson.Node, stepWithIDList *[]StepWith
if processedTools.AntPresent {
clone, repo = recursiveHandleWithTool(currentNode, stepWithIDList, processedTools, "ant", "ant", "frekele/ant:latest", variables, timeout)
}
if symbol, ok := currentNode.ParameterMap["delegate"].(map[string]interface{})["symbol"]; ok && symbol == "nodejs" {
*stepWithIDList = append(*stepWithIDList, StepWithID{Step: jenkinsjson.ConvertNodejs(currentNode), ID: id})
}
case "powershell":
*stepWithIDList = append(*stepWithIDList, StepWithID{Step: jenkinsjson.ConvertPowerShell(currentNode, variables, timeout), ID: id})

Expand Down
48 changes: 48 additions & 0 deletions convert/jenkinsjson/convertTestFiles/nodejs/Jenkinsfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
pipeline {
agent any

stages {
stage('Generate package.json') {
steps {
script {
// Create a valid JSON package.json file without comments
def packageJson = '''{
"name": "test-nodejs-plugin",
"version": "1.0.0",
"description": "Sample project to test NodeJS plugin in Jenkins",
"scripts": {
"test": "echo \\"Running tests...\\" && exit 0"
},
"dependencies": {
"lodash": "^4.17.21"
}
}'''
writeFile(file: 'package.json', text: packageJson)
}

}
}

stage('Install Packages') {
steps {
// Set up the NodeJS environment
nodejs(nodeJSInstallationName: 'node') {
sh '''
# Ensure npm uses the public registry
echo "registry=https://registry.npmjs.org/" > .npmrc
npm install
'''
}
}
}

stage('Run Tests') {
steps {
nodejs(nodeJSInstallationName: 'node') {
// Run npm test to execute the "test" script in package.json
sh 'npm test'
}
}
}
}
}
11 changes: 11 additions & 0 deletions convert/jenkinsjson/convertTestFiles/nodejs/nodejs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
- step:
identifier: stagenull99086b
name: Nodejs
spec:
command: |
npm --version
npm install
image: node:latest
shell: Sh
timeout: ""
type: Run
126 changes: 126 additions & 0 deletions convert/jenkinsjson/convertTestFiles/nodejs/nodejs_snippet.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
{
"spanId": "99086bc578544ba9",
"traceId": "8a85a96d5009b0838f1074cd9bd5984c",
"parent": "Test_Nodejs_plugin",
"all-info": "span(name: Stage: null, spanId: 99086bc578544ba9, parentSpanId: b726fb59b015ad7b, traceId: 8a85a96d5009b0838f1074cd9bd5984c, attr: harness-attribute:{\r\n \"delegate\" : {\r\n \"symbol\" : \"nodejs\",\r\n \"klass\" : null,\r\n \"arguments\" : {\r\n \"nodeJSInstallationName\" : \"Node 22\"\r\n },\r\n \"model\" : null\r\n }\r\n};harness-attribute-extra-pip: io.jenkins.plugins.opentelemetry.MigrateHarnessUrlChildAction@52416506:io.jenkins.plugins.opentelemetry.MigrateHarnessUrlChildAction@52416506;harness-attribute-extra-pip: org.jenkinsci.plugins.workflow.actions.TimingAction@4f5adbd4:org.jenkinsci.plugins.workflow.actions.TimingAction@4f5adbd4;harness-attribute-extra-pip: org.jenkinsci.plugins.workflow.support.actions.LogStorageAction@146b406d:org.jenkinsci.plugins.workflow.support.actions.LogStorageAction@146b406d;harness-others:;jenkins.pipeline.step.type:wrap;)",
"children": [
{
"spanId": "4dad6bcc1544f9b9",
"traceId": "8a85a96d5009b0838f1074cd9bd5984c",
"parent": "Test_Nodejs_plugin",
"all-info": "span(name: Stage: null, spanId: 4dad6bcc1544f9b9, parentSpanId: 99086bc578544ba9, traceId: 8a85a96d5009b0838f1074cd9bd5984c, attr: harness-attribute-extra-pip: io.jenkins.plugins.opentelemetry.MigrateHarnessUrlChildAction@3bc1da4e:io.jenkins.plugins.opentelemetry.MigrateHarnessUrlChildAction@3bc1da4e;harness-attribute-extra-pip: org.jenkinsci.plugins.workflow.actions.TimingAction@2904a805:org.jenkinsci.plugins.workflow.actions.TimingAction@2904a805;harness-others:;jenkins.pipeline.step.type:wrap;)",
"name": "Test_Nodejs_plugin #4",
"attributesMap": {
"harness-attribute-extra-pip: io.jenkins.plugins.opentelemetry.MigrateHarnessUrlChildAction@3bc1da4e": "io.jenkins.plugins.opentelemetry.MigrateHarnessUrlChildAction@3bc1da4e",
"harness-attribute-extra-pip: org.jenkinsci.plugins.workflow.actions.TimingAction@2904a805": "org.jenkinsci.plugins.workflow.actions.TimingAction@2904a805",
"harness-others": "",
"jenkins.pipeline.step.type": "wrap"
},
"type": "Run Phase Span",
"parentSpanId": "99086bc578544ba9",
"spanName": "Stage: null"
},
{
"spanId": "6020c253b602c693",
"traceId": "8a85a96d5009b0838f1074cd9bd5984c",
"parent": "Test_Nodejs_plugin",
"all-info": "span(name: Stage: null, spanId: 6020c253b602c693, parentSpanId: 99086bc578544ba9, traceId: 8a85a96d5009b0838f1074cd9bd5984c, attr: harness-attribute-extra-pip: io.jenkins.plugins.opentelemetry.MigrateHarnessUrlChildAction@17036922:io.jenkins.plugins.opentelemetry.MigrateHarnessUrlChildAction@17036922;harness-attribute-extra-pip: org.jenkinsci.plugins.workflow.actions.BodyInvocationAction@41cef527:org.jenkinsci.plugins.workflow.actions.BodyInvocationAction@41cef527;harness-attribute-extra-pip: org.jenkinsci.plugins.workflow.actions.TimingAction@325b7831:org.jenkinsci.plugins.workflow.actions.TimingAction@325b7831;harness-others:;jenkins.pipeline.step.type:wrap;)",
"children": [
{
"spanId": "470bd0cfec6f43ac",
"traceId": "8a85a96d5009b0838f1074cd9bd5984c",
"parent": "Test_Nodejs_plugin",
"all-info": "span(name: bat, spanId: 470bd0cfec6f43ac, parentSpanId: 6020c253b602c693, traceId: 8a85a96d5009b0838f1074cd9bd5984c, attr: ci.pipeline.run.user:SYSTEM;harness-attribute:{\r\n \"script\" : \"npm --version\"\r\n};harness-attribute-extra-pip: io.jenkins.plugins.opentelemetry.MigrateHarnessUrlChildAction@6fa85e2a:io.jenkins.plugins.opentelemetry.MigrateHarnessUrlChildAction@6fa85e2a;harness-attribute-extra-pip: org.jenkinsci.plugins.workflow.actions.TimingAction@637dbca1:org.jenkinsci.plugins.workflow.actions.TimingAction@637dbca1;harness-others:-WATCHING_RECURRENCE_PERIOD-staticField org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep WATCHING_RECURRENCE_PERIOD-org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep.WATCHING_RECURRENCE_PERIOD-long-USE_WATCHING-staticField org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep USE_WATCHING-org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep.USE_WATCHING-boolean-REMOTE_TIMEOUT-staticField org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep REMOTE_TIMEOUT-org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep.REMOTE_TIMEOUT-long;jenkins.pipeline.step.id:18;jenkins.pipeline.step.name:Windows Batch Script;jenkins.pipeline.step.plugin.name:workflow-durable-task-step;jenkins.pipeline.step.plugin.version:1371.vb_7cec8f3b_95e;jenkins.pipeline.step.type:bat;)",
"name": "Test_Nodejs_plugin #4",
"attributesMap": {
"harness-others": "-WATCHING_RECURRENCE_PERIOD-staticField org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep WATCHING_RECURRENCE_PERIOD-org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep.WATCHING_RECURRENCE_PERIOD-long-USE_WATCHING-staticField org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep USE_WATCHING-org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep.USE_WATCHING-boolean-REMOTE_TIMEOUT-staticField org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep REMOTE_TIMEOUT-org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep.REMOTE_TIMEOUT-long",
"jenkins.pipeline.step.name": "Windows Batch Script",
"ci.pipeline.run.user": "SYSTEM",
"jenkins.pipeline.step.id": "18",
"jenkins.pipeline.step.type": "bat",
"harness-attribute-extra-pip: org.jenkinsci.plugins.workflow.actions.TimingAction@637dbca1": "org.jenkinsci.plugins.workflow.actions.TimingAction@637dbca1",
"harness-attribute": "{\r\n \"script\" : \"npm --version\"\r\n}",
"jenkins.pipeline.step.plugin.name": "workflow-durable-task-step",
"jenkins.pipeline.step.plugin.version": "1371.vb_7cec8f3b_95e",
"harness-attribute-extra-pip: io.jenkins.plugins.opentelemetry.MigrateHarnessUrlChildAction@6fa85e2a": "io.jenkins.plugins.opentelemetry.MigrateHarnessUrlChildAction@6fa85e2a"
},
"type": "Run Phase Span",
"parentSpanId": "6020c253b602c693",
"parameterMap": { "script": "npm --version" },
"spanName": "bat"
},
{
"spanId": "4a9bac16c68a1993",
"traceId": "8a85a96d5009b0838f1074cd9bd5984c",
"parent": "Test_Nodejs_plugin",
"all-info": "span(name: Stage: null, spanId: 4a9bac16c68a1993, parentSpanId: 6020c253b602c693, traceId: 8a85a96d5009b0838f1074cd9bd5984c, attr: harness-attribute-extra-pip: io.jenkins.plugins.opentelemetry.MigrateHarnessUrlChildAction@c8a17fe:io.jenkins.plugins.opentelemetry.MigrateHarnessUrlChildAction@c8a17fe;harness-attribute-extra-pip: org.jenkinsci.plugins.workflow.actions.BodyInvocationAction@30e0409c:org.jenkinsci.plugins.workflow.actions.BodyInvocationAction@30e0409c;harness-attribute-extra-pip: org.jenkinsci.plugins.workflow.actions.TimingAction@47cf545e:org.jenkinsci.plugins.workflow.actions.TimingAction@47cf545e;harness-others:;jenkins.pipeline.step.type:wrap;)",
"name": "Test_Nodejs_plugin #4",
"attributesMap": {
"harness-attribute-extra-pip: org.jenkinsci.plugins.workflow.actions.TimingAction@47cf545e": "org.jenkinsci.plugins.workflow.actions.TimingAction@47cf545e",
"harness-others": "",
"harness-attribute-extra-pip: io.jenkins.plugins.opentelemetry.MigrateHarnessUrlChildAction@c8a17fe": "io.jenkins.plugins.opentelemetry.MigrateHarnessUrlChildAction@c8a17fe",
"jenkins.pipeline.step.type": "wrap",
"harness-attribute-extra-pip: org.jenkinsci.plugins.workflow.actions.BodyInvocationAction@30e0409c": "org.jenkinsci.plugins.workflow.actions.BodyInvocationAction@30e0409c"
},
"type": "Run Phase Span",
"parentSpanId": "6020c253b602c693",
"spanName": "Stage: null"
},
{
"spanId": "eb13aeb24d05fbb1",
"traceId": "8a85a96d5009b0838f1074cd9bd5984c",
"parent": "Test_Nodejs_plugin",
"all-info": "span(name: bat, spanId: eb13aeb24d05fbb1, parentSpanId: 6020c253b602c693, traceId: 8a85a96d5009b0838f1074cd9bd5984c, attr: ci.pipeline.run.user:SYSTEM;harness-attribute:{\r\n \"script\" : \"npm install\"\r\n};harness-attribute-extra-pip: io.jenkins.plugins.opentelemetry.MigrateHarnessUrlChildAction@5a73f798:io.jenkins.plugins.opentelemetry.MigrateHarnessUrlChildAction@5a73f798;harness-attribute-extra-pip: org.jenkinsci.plugins.workflow.actions.TimingAction@5fe91849:org.jenkinsci.plugins.workflow.actions.TimingAction@5fe91849;harness-others:-WATCHING_RECURRENCE_PERIOD-staticField org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep WATCHING_RECURRENCE_PERIOD-org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep.WATCHING_RECURRENCE_PERIOD-long-USE_WATCHING-staticField org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep USE_WATCHING-org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep.USE_WATCHING-boolean-REMOTE_TIMEOUT-staticField org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep REMOTE_TIMEOUT-org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep.REMOTE_TIMEOUT-long;jenkins.pipeline.step.id:19;jenkins.pipeline.step.name:Windows Batch Script;jenkins.pipeline.step.plugin.name:workflow-durable-task-step;jenkins.pipeline.step.plugin.version:1371.vb_7cec8f3b_95e;jenkins.pipeline.step.type:bat;)",
"name": "Test_Nodejs_plugin #4",
"attributesMap": {
"harness-others": "-WATCHING_RECURRENCE_PERIOD-staticField org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep WATCHING_RECURRENCE_PERIOD-org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep.WATCHING_RECURRENCE_PERIOD-long-USE_WATCHING-staticField org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep USE_WATCHING-org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep.USE_WATCHING-boolean-REMOTE_TIMEOUT-staticField org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep REMOTE_TIMEOUT-org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep.REMOTE_TIMEOUT-long",
"harness-attribute-extra-pip: io.jenkins.plugins.opentelemetry.MigrateHarnessUrlChildAction@5a73f798": "io.jenkins.plugins.opentelemetry.MigrateHarnessUrlChildAction@5a73f798",
"jenkins.pipeline.step.name": "Windows Batch Script",
"ci.pipeline.run.user": "SYSTEM",
"jenkins.pipeline.step.id": "19",
"jenkins.pipeline.step.type": "bat",
"harness-attribute-extra-pip: org.jenkinsci.plugins.workflow.actions.TimingAction@5fe91849": "org.jenkinsci.plugins.workflow.actions.TimingAction@5fe91849",
"harness-attribute": "{\r\n \"script\" : \"npm install\"\r\n}",
"jenkins.pipeline.step.plugin.name": "workflow-durable-task-step",
"jenkins.pipeline.step.plugin.version": "1371.vb_7cec8f3b_95e"
},
"type": "Run Phase Span",
"parentSpanId": "6020c253b602c693",
"parameterMap": { "script": "npm install" },
"spanName": "bat"
}
],
"name": "Test_Nodejs_plugin #4",
"attributesMap": {
"harness-attribute-extra-pip: io.jenkins.plugins.opentelemetry.MigrateHarnessUrlChildAction@17036922": "io.jenkins.plugins.opentelemetry.MigrateHarnessUrlChildAction@17036922",
"harness-others": "",
"jenkins.pipeline.step.type": "wrap",
"harness-attribute-extra-pip: org.jenkinsci.plugins.workflow.actions.BodyInvocationAction@41cef527": "org.jenkinsci.plugins.workflow.actions.BodyInvocationAction@41cef527",
"harness-attribute-extra-pip: org.jenkinsci.plugins.workflow.actions.TimingAction@325b7831": "org.jenkinsci.plugins.workflow.actions.TimingAction@325b7831"
},
"type": "Run Phase Span",
"parentSpanId": "99086bc578544ba9",
"spanName": "Stage: null"
}
],
"name": "Test_Nodejs_plugin #4",
"attributesMap": {
"harness-attribute-extra-pip: org.jenkinsci.plugins.workflow.support.actions.LogStorageAction@146b406d": "org.jenkinsci.plugins.workflow.support.actions.LogStorageAction@146b406d",
"harness-others": "",
"harness-attribute-extra-pip: io.jenkins.plugins.opentelemetry.MigrateHarnessUrlChildAction@52416506": "io.jenkins.plugins.opentelemetry.MigrateHarnessUrlChildAction@52416506",
"jenkins.pipeline.step.type": "wrap",
"harness-attribute": "{\r\n \"delegate\" : {\r\n \"symbol\" : \"nodejs\",\r\n \"klass\" : null,\r\n \"arguments\" : {\r\n \"nodeJSInstallationName\" : \"Node 22\"\r\n },\r\n \"model\" : null\r\n }\r\n}",
"harness-attribute-extra-pip: org.jenkinsci.plugins.workflow.actions.TimingAction@4f5adbd4": "org.jenkinsci.plugins.workflow.actions.TimingAction@4f5adbd4"
},
"type": "Run Phase Span",
"parentSpanId": "b726fb59b015ad7b",
"parameterMap": {
"delegate": {
"symbol": "nodejs",
"klass": null,
"arguments": { "nodeJSInstallationName": "Node 22" },
"model": null
}
},
"spanName": "Stage: null"
}
46 changes: 46 additions & 0 deletions convert/jenkinsjson/json/nodejs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package json

import (
harness "github.com/drone/spec/dist/go"
)

// ConvertNodejs creates a Harness step for nunit plugin.
func ConvertNodejs(node Node) *harness.Step {
// Recursively process children
var script string
processNodejsScript(node, &script)
convertNodeJs := &harness.Step{
Name: "Nodejs",
Type: "script",
Id: SanitizeForId(node.SpanName, node.SpanId),
Spec: &harness.StepExec{
Connector: "<+input_docker_hub_connector>",
Image: "node:latest",
Shell: "sh",
Run: script,
},
}

return convertNodeJs
}

func processNodejsScript(currentNode Node, result *string) {
for _, child := range currentNode.Children {
processNode(child, result)
}
}

func processNode(node Node, result *string) {
if stepType, exists := node.AttributesMap["jenkins.pipeline.step.type"]; exists {
switch stepType {
case "wrap":
for _, child := range node.Children {
processNode(child, result)
}
case "bat", "sh":
if script, ok := node.ParameterMap["script"].(string); ok {
*result += script + "\n"
}
}
}
}
34 changes: 34 additions & 0 deletions convert/jenkinsjson/json/nodejs_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package json

import (
"testing"

harness "github.com/drone/spec/dist/go"
"github.com/google/go-cmp/cmp"
)

func TestConvertNodejs(t *testing.T) {

var tests []runner
tests = append(tests, prepare(t, "/nodejs/nodejs_snippet", &harness.Step{
Id: "Stage_null99086b",
Name: "Nodejs",
Type: "script",
Spec: &harness.StepExec{
Connector: "<+input_docker_hub_connector>",
Image: "node:latest",
Shell: "sh",
Run: "npm --version\nnpm install\n",
},
}))

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := ConvertNodejs(tt.input)

if diff := cmp.Diff(got, tt.want); diff != "" {
t.Errorf("ConvertNodejs() mismatch (-want +got):\n%s", diff)
}
})
}
}
25 changes: 25 additions & 0 deletions samples/jenkins/Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -751,3 +751,28 @@ line3'''
}
}
}

//Nodejs conversion Step
stage('Install Packages') {
steps {
// Set up the NodeJS environment
nodejs(nodeJSInstallationName: 'node') {
sh '''
# Ensure npm uses the public registry
echo "registry=https://registry.npmjs.org/" > .npmrc
npm install
'''
}
}
}

stage('Run Tests') {
steps {
nodejs(nodeJSInstallationName: 'node') {
// Run npm test to execute the "test" script in package.json
sh 'npm test'
}
}
}
}
}