Skip to content

Commit cf191ff

Browse files
authored
fix missing behaviors and packages tabs (fixes #3351, via #3353)
1 parent 2123a09 commit cf191ff

4 files changed

Lines changed: 195 additions & 13 deletions

File tree

.github/workflows/build.yaml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,28 @@ jobs:
106106
run: ./bin/allure --version
107107
- name: Generate demo report
108108
run: ./bin/allure generate testcmd-smoke-results
109+
- name: Verify generated tree data
110+
shell: pwsh
111+
run: |
112+
$requiredFiles = @(
113+
'allure-report/data/behaviors.json',
114+
'allure-report/data/behaviors.csv',
115+
'allure-report/data/packages.json',
116+
'allure-report/widgets/behaviors.json'
117+
)
118+
119+
$missingFiles = $requiredFiles | Where-Object {
120+
-not (Test-Path -LiteralPath $_ -PathType Leaf)
121+
}
122+
123+
if ($missingFiles.Count -gt 0) {
124+
Write-Error "Missing generated report files: $($missingFiles -join ', ')"
125+
exit 1
126+
}
127+
128+
$requiredFiles | ForEach-Object {
129+
Write-Host "Verified $_"
130+
}
109131
report:
110132
needs: [build, testcmd]
111133
name: "Build report"

allure-commandline/build.gradle.kts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,6 @@ tasks.distTar {
5252
val startScripts by tasks.existing(CreateStartScripts::class) {
5353
applicationName = "allure"
5454
classpath = files(tasks.jar) + configurations.runtimeClasspath.get() + files("src/lib/config")
55-
doLast {
56-
unixScript.writeText(unixScript.readText()
57-
.replace(Regex("(?m)^APP_HOME="), "export APP_HOME=")
58-
.replace("\$(uname)\" = \"Darwin", "")
59-
)
60-
}
6155
}
6256

6357
tasks.build {

allure-commandline/src/main/java/io/qameta/allure/CommandLine.java

Lines changed: 73 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,14 @@
2727

2828
import java.io.PrintWriter;
2929
import java.io.StringWriter;
30+
import java.net.URI;
31+
import java.net.URISyntaxException;
32+
import java.nio.file.FileSystemNotFoundException;
33+
import java.nio.file.Files;
3034
import java.nio.file.Path;
3135
import java.nio.file.Paths;
36+
import java.nio.file.ProviderNotFoundException;
37+
import java.security.CodeSource;
3238
import java.util.List;
3339
import java.util.Objects;
3440
import java.util.Optional;
@@ -51,6 +57,10 @@ public class CommandLine {
5157
protected static final String GENERATE_COMMAND = "generate";
5258
protected static final String OPEN_COMMAND = "open";
5359
protected static final String PLUGIN_COMMAND = "plugin";
60+
private static final String CONFIG_DIRECTORY = "config";
61+
private static final String PLUGINS_DIRECTORY = "plugins";
62+
private static final String DEFAULT_CONFIG_FILE_NAME = "allure.yml";
63+
private static final String LIB_DIRECTORY = "lib";
5464

5565
private final MainCommand mainCommand;
5666
private final ServeCommand serveCommand;
@@ -80,20 +90,76 @@ public CommandLine(final Commands commands) {
8090
}
8191

8292
public static void main(final String[] args) throws InterruptedException {
83-
final String allureHome = System.getenv("APP_HOME");
84-
final CommandLine commandLine;
85-
if (Objects.isNull(allureHome)) {
86-
commandLine = new CommandLine((Path) null);
87-
LOGGER.info("APP_HOME is not set, using default configuration");
88-
} else {
89-
commandLine = new CommandLine(Paths.get(allureHome));
93+
final Optional<Path> allureHome = resolveAllureHome(System.getenv("APP_HOME"));
94+
if (!allureHome.isPresent()) {
95+
LOGGER.info("Allure home is not set, using default configuration");
9096
}
97+
final CommandLine commandLine = new CommandLine(allureHome.orElse(null));
9198
final ExitCode exitCode = commandLine
9299
.parse(args)
93100
.orElseGet(commandLine::run);
94101
System.exit(exitCode.getCode());
95102
}
96103

104+
static Optional<Path> resolveAllureHome(final String allureHome, final URI codeSource) {
105+
if (Objects.nonNull(allureHome)) {
106+
return Optional.of(Paths.get(allureHome));
107+
}
108+
return inferAllureHome(codeSource);
109+
}
110+
111+
private static Optional<Path> resolveAllureHome(final String allureHome) {
112+
if (Objects.nonNull(allureHome)) {
113+
return Optional.of(Paths.get(allureHome));
114+
}
115+
return getCodeSource()
116+
.flatMap(CommandLine::inferAllureHome);
117+
}
118+
119+
private static Optional<URI> getCodeSource() {
120+
try {
121+
return Optional.ofNullable(CommandLine.class.getProtectionDomain().getCodeSource())
122+
.map(CodeSource::getLocation)
123+
.map(location -> {
124+
try {
125+
return location.toURI();
126+
} catch (URISyntaxException e) {
127+
LOGGER.debug("Could not resolve commandline location", e);
128+
return null;
129+
}
130+
});
131+
} catch (SecurityException e) {
132+
LOGGER.debug("Could not access commandline location", e);
133+
return Optional.empty();
134+
}
135+
}
136+
137+
private static Optional<Path> inferAllureHome(final URI codeSource) {
138+
try {
139+
final Path location = Paths.get(codeSource).toAbsolutePath().normalize();
140+
final Path lib = Files.isDirectory(location) ? location : location.getParent();
141+
if (Objects.isNull(lib)
142+
|| Objects.isNull(lib.getFileName())
143+
|| !LIB_DIRECTORY.equals(lib.getFileName().toString())) {
144+
return Optional.empty();
145+
}
146+
final Path home = lib.getParent();
147+
return isAllureHome(home)
148+
? Optional.of(home)
149+
: Optional.empty();
150+
} catch (IllegalArgumentException | FileSystemNotFoundException | ProviderNotFoundException
151+
| SecurityException e) {
152+
LOGGER.debug("Could not infer Allure home from commandline location {}", codeSource, e);
153+
return Optional.empty();
154+
}
155+
}
156+
157+
private static boolean isAllureHome(final Path home) {
158+
return Objects.nonNull(home)
159+
&& Files.isRegularFile(home.resolve(CONFIG_DIRECTORY).resolve(DEFAULT_CONFIG_FILE_NAME))
160+
&& Files.isDirectory(home.resolve(PLUGINS_DIRECTORY));
161+
}
162+
97163
public Optional<ExitCode> parse(final String... args) {
98164
if (args.length == 0) {
99165
printUsage(commander);

allure-commandline/src/test/java/io/qameta/allure/CommandLineTest.java

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import org.mockito.ArgumentCaptor;
2727

2828
import java.io.IOException;
29+
import java.net.URI;
2930
import java.nio.file.Files;
3031
import java.nio.file.Path;
3132
import java.util.Arrays;
@@ -62,6 +63,54 @@ void setUp() {
6263
this.commandLine = new CommandLine(commands);
6364
}
6465

66+
/**
67+
* Verifies the explicit application home is used as the commandline home.
68+
* The test checks APP_HOME has priority over the commandline location.
69+
*/
70+
@Description
71+
@Test
72+
void shouldResolveAllureHomeFromAppHome(@TempDir final Path temp) {
73+
final Path appHome = temp.resolve("custom-home");
74+
final URI commandlineLocation = temp.resolve("allure").resolve("lib").resolve("allure-commandline.jar")
75+
.toUri();
76+
77+
final Optional<Path> result = resolveAllureHome(appHome.toString(), commandlineLocation);
78+
79+
assertThat(result)
80+
.hasValue(appHome);
81+
}
82+
83+
/**
84+
* Verifies the commandline can infer an installed distribution home.
85+
* The test checks a commandline jar under lib resolves to the parent distribution directory.
86+
*/
87+
@Description
88+
@Test
89+
void shouldInferAllureHomeFromCommandlineJar(@TempDir final Path temp) throws IOException {
90+
final Path allureHome = createAllureHome(temp);
91+
final Path commandlineJar = createCommandlineJar(allureHome);
92+
93+
final Optional<Path> result = resolveAllureHome(null, commandlineJar.toUri());
94+
95+
assertThat(result)
96+
.hasValue(allureHome);
97+
}
98+
99+
/**
100+
* Verifies invalid commandline locations are ignored.
101+
* The test checks a candidate without distribution config and plugins does not resolve.
102+
*/
103+
@Description
104+
@Test
105+
void shouldIgnoreInvalidInferredAllureHome(@TempDir final Path temp) throws IOException {
106+
final Path commandlineJar = createCommandlineJar(temp.resolve("invalid-allure"));
107+
108+
final Optional<Path> result = resolveAllureHome(null, commandlineJar.toUri());
109+
110+
assertThat(result)
111+
.isEmpty();
112+
}
113+
65114
/**
66115
* Verifies that invoking the parser without arguments is rejected.
67116
* The test checks the command line reports an argument parsing error.
@@ -582,4 +631,55 @@ private String describeMainCommand() {
582631
verboseOptions.isQuiet()
583632
);
584633
}
634+
635+
@Step("Create installed Allure home")
636+
private Path createAllureHome(final Path temp) throws IOException {
637+
final Path allureHome = temp.resolve("allure");
638+
Files.createDirectories(allureHome.resolve("config"));
639+
Files.write(allureHome.resolve("config").resolve("allure.yml"), Arrays.asList("plugins: []"));
640+
Files.createDirectories(allureHome.resolve("plugins"));
641+
Allure.addAttachment(
642+
"allure-home-layout.txt",
643+
"text/plain",
644+
String.format(
645+
"home=%s%nconfig=%s%nplugins=%s%n",
646+
allureHome,
647+
allureHome.resolve("config").resolve("allure.yml"),
648+
allureHome.resolve("plugins")
649+
),
650+
".txt"
651+
);
652+
return allureHome;
653+
}
654+
655+
@Step("Create commandline jar")
656+
private Path createCommandlineJar(final Path allureHome) throws IOException {
657+
final Path lib = Files.createDirectories(allureHome.resolve("lib"));
658+
final Path commandlineJar = lib.resolve("allure-commandline-test.jar");
659+
Files.write(commandlineJar, Arrays.asList("commandline jar marker"));
660+
Allure.addAttachment(
661+
"commandline-location.txt",
662+
"text/plain",
663+
String.format("commandlineJar=%s%n", commandlineJar),
664+
".txt"
665+
);
666+
return commandlineJar;
667+
}
668+
669+
@Step("Resolve Allure home")
670+
private Optional<Path> resolveAllureHome(final String appHome, final URI commandlineLocation) {
671+
final Optional<Path> result = CommandLine.resolveAllureHome(appHome, commandlineLocation);
672+
Allure.addAttachment(
673+
"allure-home-resolution.txt",
674+
"text/plain",
675+
String.format(
676+
"appHome=%s%ncommandlineLocation=%s%nresolvedHome=%s%n",
677+
appHome,
678+
commandlineLocation,
679+
result.map(Path::toString).orElse("<empty>")
680+
),
681+
".txt"
682+
);
683+
return result;
684+
}
585685
}

0 commit comments

Comments
 (0)