diff --git a/LICENSE.md b/LICENSE.md index 7d5045b8..b40270f1 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,25 +1,25 @@ -The MIT License (MIT) -===================== - -Copyright © `2020` `First Bit Semenovskaya, Первый Бит Семеновская` - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the “Software”), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. +The MIT License (MIT) +===================== + +Copyright © `2020` `First Bit Semenovskaya, Первый Бит Семеновская` + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the “Software”), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy index 7bffcc1b..43bb739f 100644 --- a/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy +++ b/src/ru/pulsar/jenkins/library/steps/Yaxunit.groovy @@ -86,7 +86,10 @@ class Yaxunit implements Serializable, Coverable { FilePath pathToAllureReport = FileUtils.getFilePath("$env.WORKSPACE/$allureReport") String allureReportDir = FileUtils.getLocalPath(pathToAllureReport.getParent()) - pathToJUnitReport.copyTo(pathToAllureReport) + String pathToJUnitReportString = pathToJUnitReport.getRemote() + if (steps.fileExists(pathToJUnitReportString)) { + pathToJUnitReport.copyTo(pathToAllureReport) + } steps.stash(YAXUNIT_ALLURE_STASH, "$allureReportDir/**", true) } diff --git a/src/ru/pulsar/jenkins/library/utils/FileUtils.groovy b/src/ru/pulsar/jenkins/library/utils/FileUtils.groovy index 721f6800..d64288df 100644 --- a/src/ru/pulsar/jenkins/library/utils/FileUtils.groovy +++ b/src/ru/pulsar/jenkins/library/utils/FileUtils.groovy @@ -29,17 +29,20 @@ class FileUtils { static String getLocalPath(FilePath filePath) { IStepExecutor steps = ContextRegistry.getContext().getStepExecutor() + String workspacePath = steps.env().WORKSPACE + String fileRemotePath = filePath.getRemote() - def env = steps.env(); + // Нормализуем пути: заменяем обратные слэши на прямые + workspacePath = workspacePath.replace('\\', '/') + fileRemotePath = fileRemotePath.replace('\\', '/') - Path workspacePath = new File(env.WORKSPACE).toPath() - Path rawFilePath = new File(filePath.getRemote()).toPath() + // Проверяем, что файл находится внутри рабочей директории + if (!fileRemotePath.startsWith(workspacePath)) { + throw new IllegalArgumentException("File path is not within the workspace directory") + } - return workspacePath.relativize(rawFilePath) - .toString() - .replaceAll('\\\\\\\\', '/') - .replaceAll('\\\\', '/') - .toString() + // Вычисляем относительный путь + return fileRemotePath.substring(workspacePath.length() + 1) } static void loadFile(String filePathFrom, def env, String filePathTo) { diff --git a/test/unit/groovy/ru/pulsar/jenkins/library/utils/EnvUtils.java b/test/unit/groovy/ru/pulsar/jenkins/library/utils/EnvUtils.java index 629c6561..618fc8f3 100644 --- a/test/unit/groovy/ru/pulsar/jenkins/library/utils/EnvUtils.java +++ b/test/unit/groovy/ru/pulsar/jenkins/library/utils/EnvUtils.java @@ -7,7 +7,7 @@ public class EnvUtils implements EnvironmentAction { - public String NODE_NAME = "node"; + public String NODE_NAME = "built-in"; public String WORKSPACE = "ws"; public String BRANCH_NAME = "master"; diff --git a/test/unit/groovy/ru/pulsar/jenkins/library/utils/FileUtilsTest.java b/test/unit/groovy/ru/pulsar/jenkins/library/utils/FileUtilsTest.java new file mode 100644 index 00000000..99a6dd89 --- /dev/null +++ b/test/unit/groovy/ru/pulsar/jenkins/library/utils/FileUtilsTest.java @@ -0,0 +1,32 @@ +package ru.pulsar.jenkins.library.utils; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import ru.pulsar.jenkins.library.IStepExecutor; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.when; + +class FileUtilsTest { + + private final IStepExecutor steps = TestUtils.getMockedStepExecutor(); + + @BeforeEach + void setUp() { + TestUtils.setupMockedContext(steps); + } + + @Test + void testGetLocalPath() { + // given + var env = new EnvUtils(); + when(steps.env()).thenReturn(env); + var filePath = FileUtils.getFilePath(env.WORKSPACE + "/src/cf"); + + // when + String localPath = FileUtils.getLocalPath(filePath); + + // then + assertThat(localPath).isEqualTo("src/cf"); + } +}