Skip to content

Commit 2f9fd7f

Browse files
committed
use attachment paths relative to build workspace root
1 parent f3a43ca commit 2f9fd7f

1 file changed

Lines changed: 42 additions & 23 deletions

File tree

java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/core/ScreenShotRule.java

Lines changed: 42 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
import java.io.InputStream;
77
import java.nio.file.Files;
88
import java.nio.file.Path;
9-
import java.nio.file.StandardCopyOption;
109
import java.util.UUID;
1110
import java.util.logging.Level;
1211
import java.util.logging.Logger;
@@ -72,34 +71,54 @@ private void captureScreenshots(ExtensionContext context) {
7271
if (driver instanceof TakesScreenshot) {
7372
source = new ByteArrayInputStream(((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES));
7473
}
75-
try {
76-
final File destinationDir = new File(screenshotFolder, context.getRequiredTestClass().getName());
77-
destinationDir.mkdirs();
78-
final File destination = new File(destinationDir, filename + SCREENSHOT_FILE_EXTENSION);
79-
// copy screenshot
80-
Files.copy(source, destination.toPath(), StandardCopyOption.REPLACE_EXISTING);
81-
// base folder as Path (correct way)
82-
final Path base = screenshotFolder.toPath().toAbsolutePath().normalize();
83-
final Path file = destination.toPath().toAbsolutePath().normalize();
84-
// relative path for Jenkins attachment plugin
85-
final Path relative = base.relativize(file);
86-
// ATTENTION: required for JUnit Attachment Plugin
87-
final String attachmentLine = String.format(ATTACHMENT_FORMAT, relative.toString().replace("\\", "/"));
88-
System.out.println(attachmentLine);
89-
System.out.flush(); // replaced System.out may not auto-flush
90-
// duplicate to System.err because tycho-surefire may read test stuff from there
91-
System.err.println(attachmentLine);
92-
System.err.flush(); // replaced System.err may not auto-flush
93-
} catch (IOException exception) {
94-
throw new RuntimeException(exception);
95-
}
74+
final File destinationDir = new File(screenshotFolder, context.getRequiredTestClass().getName());
75+
destinationDir.mkdirs();
76+
final File destination = new File(destinationDir, filename + SCREENSHOT_FILE_EXTENSION);
77+
// Absolute path to the screenshot file
78+
final Path absoluteFile = destination.toPath().toAbsolutePath().normalize();
79+
// Jenkins JUnit Attachments Plugin resolves [[ATTACHMENT|<path>]] markers against
80+
// the build's workspace root ($WORKSPACE), not against the directory containing the
81+
// JUnit XML. So we relativize against the workspace root (the repo root, identified
82+
// by walking up to the enclosing .git directory) and emit a workspace-relative path.
83+
final Path workspaceRoot = findWorkspaceRoot(absoluteFile);
84+
final Path attachmentPath = workspaceRoot != null
85+
? workspaceRoot.relativize(absoluteFile)
86+
: screenshotFolder.toPath().toAbsolutePath().normalize().relativize(absoluteFile);
87+
// ATTENTION: required for JUnit Attachment Plugin
88+
final String attachmentLine = String.format(ATTACHMENT_FORMAT,
89+
attachmentPath.toString().replace("\\", "/")) + System.lineSeparator();
90+
System.out.print(attachmentLine);
91+
System.out.flush();
92+
System.err.print(attachmentLine);
93+
System.err.flush();
9694
} catch (Exception e) {
9795
logger.log(Level.WARNING, "Could not capture screenshot for window: " + window.getWindowHandle(), e);
9896
}
9997
});
10098
}
10199
}
102-
100+
101+
/**
102+
* Walks up from the given path until it finds a directory containing a {@code .git}
103+
* entry (file or directory — submodule worktrees use a file). Returns that ancestor
104+
* directory, which corresponds to the Jenkins build workspace root for repository
105+
* checkouts. Returns {@code null} if no such ancestor exists (e.g. running outside
106+
* any git checkout), in which case callers should fall back to a different base.
107+
*/
108+
private static Path findWorkspaceRoot(final Path startFrom) {
109+
Path current = startFrom.toAbsolutePath().normalize();
110+
if (Files.isRegularFile(current)) {
111+
current = current.getParent();
112+
}
113+
while (current != null) {
114+
if (Files.exists(current.resolve(".git"))) {
115+
return current;
116+
}
117+
current = current.getParent();
118+
}
119+
return null;
120+
}
121+
103122
private InputStream getScreenshotNotSupportedImage() {
104123
return AbstractSeleniumTest.class.getResourceAsStream(NOT_SUPPORTED_IMAGE);
105124
}

0 commit comments

Comments
 (0)