diff --git a/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/Pipeline.kt b/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/Pipeline.kt index 2c1f7d8..4b4a309 100644 --- a/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/Pipeline.kt +++ b/core/src/main/kotlin/com/code42/jenkins/pipelinekt/core/Pipeline.kt @@ -77,13 +77,14 @@ data class Pipeline( } else if (useMultibranchWorkspace) { writer.writeln("// Calculate custom workspace for multibranch pipelines") writer.writeln("// This prevents workspace path truncation and branch conflicts") - writer.writeln("// by using a relative path that includes the sanitized branch name") + writer.writeln("// by using a relative path that includes the sanitized job name") writer.writeln("def customWorkspacePath = null") writer.writeln("if (env.BRANCH_NAME) {") val innerWriter = writer.inner() - innerWriter.writeln("// Replace slashes and other special characters with underscores for safe filesystem paths") - innerWriter.writeln("def safeBranch = env.BRANCH_NAME.replaceAll('/', '_').replaceAll(/[^A-Za-z0-9._-]/, '_')") - innerWriter.writeln("customWorkspacePath = \"./workspace//\${safeBranch}\"") + innerWriter.writeln("// Decode URL-encoded characters (e.g., %2F -> /) from job name and sanitize for safe filesystem paths") + innerWriter.writeln("def decodedJobName = java.net.URLDecoder.decode(env.JOB_NAME, 'UTF-8')") + innerWriter.writeln("def safeJobName = decodedJobName.replaceAll(/[^A-Za-z0-9._-]/, '_')") + innerWriter.writeln("customWorkspacePath = \"./workspace//\${safeJobName}\"") writer.writeln("}") writer.writeln("") } diff --git a/core/src/test/kotlin/com/code42/jenkins/pipelinekt/core/PipelineWorkspaceTest.kt b/core/src/test/kotlin/com/code42/jenkins/pipelinekt/core/PipelineWorkspaceTest.kt index 27cacda..db8a1ae 100644 --- a/core/src/test/kotlin/com/code42/jenkins/pipelinekt/core/PipelineWorkspaceTest.kt +++ b/core/src/test/kotlin/com/code42/jenkins/pipelinekt/core/PipelineWorkspaceTest.kt @@ -31,13 +31,11 @@ class PipelineWorkspaceTest { println(result) // Verify it contains the runtime check - assertTrue(result.contains("if (env.BRANCH_NAME)"), "Should check for BRANCH_NAME") - assertTrue(result.contains("def rootDir = new File(env.WORKSPACE).parentFile.parent")) - assertTrue(result.contains("def safeBranch = (env.BRANCH_NAME ?: 'unknown').replaceAll(/[^A-Za-z0-9._-]/, '_')")) - assertTrue(result.contains("def customPath")) - assertTrue(result.contains("ws(customPath)")) - assertTrue(result.contains("checkout scm")) - assertTrue(result.contains("else {"), "Should have else block for non-multibranch") + assertTrue(result.contains("if (env.BRANCH_NAME)"), "Should check for BRANCH_NAME to detect multibranch") + assertTrue(result.contains("def decodedJobName = java.net.URLDecoder.decode(env.JOB_NAME, 'UTF-8')"), "Should decode URL-encoded job name") + assertTrue(result.contains("def safeJobName = decodedJobName.replaceAll(/[^A-Za-z0-9._-]/, '_')"), "Should sanitize job name") + assertTrue(result.contains("customWorkspacePath"), "Should define customWorkspacePath") + assertTrue(result.contains("customWorkspace customWorkspacePath"), "Should use customWorkspacePath in agent") } @Test @@ -61,9 +59,8 @@ class PipelineWorkspaceTest { println(result) // Verify it uses custom workspace directly - assertTrue(result.contains("def customPath = \"/my/custom/workspace\"")) - assertTrue(result.contains("ws(customPath)")) - assertTrue(result.contains("checkout scm")) + assertTrue(result.contains("def customWorkspacePath = \"/my/custom/workspace\""), "Should define customWorkspacePath with custom value") + assertTrue(result.contains("customWorkspace customWorkspacePath"), "Should use customWorkspacePath in agent") assertTrue(!result.contains("if (env.BRANCH_NAME)"), "Should NOT check for BRANCH_NAME when custom workspace is set") } @@ -87,10 +84,9 @@ class PipelineWorkspaceTest { println("\n=== Generated Jenkinsfile with useMultibranchWorkspace=false ===") println(result) - // Verify it doesn't use any workspace wrapping - assertTrue(!result.contains("ws("), "Should NOT use ws() wrapper") - assertTrue(!result.contains("customPath"), "Should NOT have customPath") - assertTrue(!result.contains("checkout scm"), "Should NOT have checkout scm") + // Verify it doesn't use any custom workspace logic + assertTrue(!result.contains("customWorkspacePath"), "Should NOT have customWorkspacePath") + assertTrue(!result.contains("if (env.BRANCH_NAME)"), "Should NOT check for BRANCH_NAME") assertTrue(result.contains("stages {"), "Should have stages block directly") } } diff --git a/version.txt b/version.txt index e9f83de..e129616 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -0.21.13 \ No newline at end of file +0.21.14 \ No newline at end of file