Skip to content

Commit a4350aa

Browse files
committed
Log stderr when executing env files
1 parent 0444729 commit a4350aa

File tree

9 files changed

+103
-23
lines changed

9 files changed

+103
-23
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22
All notable changes to this project will be documented in this file.
33
This project adheres to [Semantic Versioning].
44

5+
## Unreleased
6+
7+
### Added
8+
9+
- When environment variables file is executed, it now receives all environment variables accumulated by previous entries
10+
- Log stderr from execution of environment variables files into IDE event console
11+
512
## 3.3.0 - 2022-10-02
613

714
### Added

modules/core/src/main/java/net/ashald/envfile/EnvVarsProviderFactory.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
package net.ashald.envfile;
22

33
import java.util.Map;
4+
import java.util.function.Consumer;
45

56

67
public interface EnvVarsProviderFactory {
78

89
/**
910
* @param baseEnvVars env vars defined in the run configuration
1011
*/
11-
EnvVarsProvider createProvider(Map<String, String> baseEnvVars);
12+
EnvVarsProvider createProvider(Map<String, String> baseEnvVars, Consumer<String> logger);
1213

1314
String getTitle();
1415

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package net.ashald.envfile.providers;
22

3+
import lombok.Builder;
4+
import lombok.NonNull;
5+
import lombok.Value;
36
import lombok.val;
47
import net.ashald.envfile.exceptions.InvalidEnvFileException;
58

@@ -9,7 +12,7 @@
912
import java.io.InputStreamReader;
1013
import java.nio.charset.StandardCharsets;
1114
import java.util.Map;
12-
import java.util.stream.Collectors;
15+
import java.util.stream.Stream;
1316

1417
/**
1518
* Execute given command with given environment, and return standard output
@@ -19,30 +22,46 @@
1922
public interface EnvFileExecutor {
2023
EnvFileExecutor DEFAULT = new ReadStdoutAsUtf8();
2124

22-
String execute(String cmd, Map<String, String> environment) throws InvalidEnvFileException;
25+
Output execute(String cmd, Map<String, String> environment) throws InvalidEnvFileException;
26+
27+
@Value
28+
@Builder
29+
class Output {
30+
@NonNull
31+
private final Stream<String> stderr;
32+
33+
@NonNull
34+
private final Stream<String> stdout;
35+
}
2336

2437
class ReadStdoutAsUtf8 implements EnvFileExecutor {
2538

2639
@Override
27-
public String execute(String cmd, Map<String, String> environment) throws InvalidEnvFileException {
40+
public Output execute(String cmd, Map<String, String> environment) throws InvalidEnvFileException {
2841
val processBuilder = new ProcessBuilder(cmd);
2942
processBuilder.environment().putAll(environment);
3043
try {
3144
val process = processBuilder.start();
3245
val stdout = process.getInputStream();
33-
return dumpStream(stdout);
46+
val stderr = process.getErrorStream();
47+
return Output.builder()
48+
.stdout(
49+
streamLines(stdout)
50+
)
51+
.stderr(
52+
streamLines(stderr)
53+
)
54+
.build();
3455
} catch (IOException e) {
3556
throw new InvalidEnvFileException(e);
3657
}
3758
}
3859

39-
40-
private static String dumpStream(final InputStream inputStream) {
60+
private static Stream<String> streamLines(final InputStream inputStream) {
4161
val reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
4262

4363
return new BufferedReader(reader)
44-
.lines()
45-
.collect(Collectors.joining("\n"));
64+
.lines();
4665
}
4766
}
4867
}

modules/core/src/main/java/net/ashald/envfile/providers/SingleFileEnvVarsProvider.java

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,13 @@
44
import lombok.val;
55
import net.ashald.envfile.EnvVarsProvider;
66
import net.ashald.envfile.exceptions.EnvFileException;
7+
import net.ashald.envfile.exceptions.InvalidEnvFileException;
78
import org.jetbrains.annotations.NotNull;
89

910
import java.io.File;
1011
import java.util.Map;
12+
import java.util.function.Consumer;
13+
import java.util.stream.Collectors;
1114

1215
@Builder
1316
public class SingleFileEnvVarsProvider implements EnvVarsProvider {
@@ -21,14 +24,34 @@ public class SingleFileEnvVarsProvider implements EnvVarsProvider {
2124
@NotNull
2225
private final EnvFileParser parser;
2326

27+
private final Consumer<String> logger;
28+
2429
@Override
25-
public Map<String, String> getEnvVars(File file, boolean isExecutable, Map<String, String> context)
30+
public Map<String, String> getEnvVars(
31+
final File file,
32+
final boolean isExecutable,
33+
final Map<String, String> context
34+
)
2635
throws EnvFileException {
2736

2837
val content = isExecutable
29-
? executor.execute(file.getAbsolutePath(), context)
38+
? execute(file.getAbsolutePath(), context)
3039
: reader.read(file);
3140

3241
return parser.parse(content);
3342
}
43+
44+
private String execute(String cmd, Map<String, String> context) throws InvalidEnvFileException {
45+
val output = executor.execute(cmd, context);
46+
47+
if (logger != null) {
48+
logger.accept(
49+
output.getStderr()
50+
.map(line -> "STDERR: " + line)
51+
.collect(Collectors.joining("\n"))
52+
);
53+
}
54+
return output.getStdout()
55+
.collect(Collectors.joining("\n"));
56+
}
3457
}

modules/core/src/main/java/net/ashald/envfile/providers/dotenv/DotEnvFileParserFactory.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,17 @@
88
import org.jetbrains.annotations.NotNull;
99

1010
import java.util.Map;
11+
import java.util.function.Consumer;
1112

1213
public class DotEnvFileParserFactory implements EnvVarsProviderFactory {
1314

1415
@Override
15-
public EnvVarsProvider createProvider(Map<String, String> baseEnvVars) {
16+
public EnvVarsProvider createProvider(Map<String, String> baseEnvVars, Consumer<String> logger) {
1617
return SingleFileEnvVarsProvider.builder()
1718
.reader(EnvFileReader.DEFAULT)
1819
.executor(EnvFileExecutor.DEFAULT)
1920
.parser(DotEnvFileParser.INSTANCE)
21+
.logger(logger)
2022
.build();
2123
}
2224

modules/core/src/main/java/net/ashald/envfile/providers/runconfig/RunConfigEnvVarsProviderFactory.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@
55
import org.jetbrains.annotations.NotNull;
66

77
import java.util.Map;
8+
import java.util.function.Consumer;
89

910
public class RunConfigEnvVarsProviderFactory implements EnvVarsProviderFactory {
1011

1112
@Override
12-
public EnvVarsProvider createProvider(Map<String, String> baseEnvVars) {
13+
public EnvVarsProvider createProvider(Map<String, String> baseEnvVars, Consumer<String> logger) {
1314
return new RunConfigEnvVarsProvider(baseEnvVars);
1415
}
1516

modules/core/src/main/java/net/ashald/envfile/providers/yaml/YamlEnvFileParserFactory.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,20 @@
99
import org.yaml.snakeyaml.Yaml;
1010

1111
import java.util.Map;
12+
import java.util.function.Consumer;
1213

1314
public class YamlEnvFileParserFactory implements EnvVarsProviderFactory {
1415
private static final Yaml YAML = new Yaml();
1516

1617
@Override
17-
public EnvVarsProvider createProvider(Map<String, String> baseEnvVars) {
18+
public EnvVarsProvider createProvider(Map<String, String> baseEnvVars, Consumer<String> logger) {
1819
return SingleFileEnvVarsProvider.builder()
1920
.reader(EnvFileReader.DEFAULT)
2021
.executor(EnvFileExecutor.DEFAULT)
2122
.parser(
2223
new YamlEnvFileParser(YAML)
2324
)
25+
.logger(logger)
2426
.build();
2527
}
2628

modules/platform/src/main/java/net/ashald/envfile/platform/EnvFileEnvironmentVariables.java

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,28 @@
22

33
import com.intellij.execution.ExecutionException;
44
import com.intellij.execution.configurations.GeneralCommandLine;
5+
import com.intellij.notification.Notification;
6+
import com.intellij.notification.NotificationType;
7+
import com.intellij.notification.Notifications;
58
import com.intellij.openapi.components.PathMacroManager;
69
import com.intellij.openapi.project.Project;
710
import lombok.Builder;
811
import lombok.RequiredArgsConstructor;
912
import lombok.val;
10-
import lombok.var;
1113
import net.ashald.envfile.EnvVarsProvider;
1214
import net.ashald.envfile.exceptions.EnvFileException;
1315
import net.ashald.envfile.exceptions.InvalidEnvFileException;
1416
import org.apache.commons.text.StringSubstitutor;
1517
import org.jetbrains.annotations.NotNull;
1618

19+
import java.io.File;
1720
import java.util.HashMap;
1821
import java.util.Map;
1922

2023
@Builder
2124
@RequiredArgsConstructor
2225
public class EnvFileEnvironmentVariables {
26+
private static final String NOTIFICATION_GROUP = "net.ashald.envfile";
2327

2428
private final ProjectFileResolver projectFileResolver = ProjectFileResolver.DEFAULT;
2529
private final EnvFileSettings envFileSettings;
@@ -56,11 +60,11 @@ public Map<String, String> render(
5660
}
5761

5862
try {
59-
val envVarsProvider = resolveEnvVarsProvider(entry.getParserId(), baseEnv);
60-
val file = projectFileResolver.resolvePath(project, entry.getPath()).orElse(null);
63+
val file = projectFileResolver.resolvePath(project, entry.getPath());
64+
val envVarsProvider = resolveEnvVarsProvider(project, baseEnv, entry);
6165

6266
envVarsProvider
63-
.getEnvVars(file, entry.isExecutable(), result)
67+
.getEnvVars(file.orElse(null), entry.isExecutable(), result)
6468
.forEach(
6569
(key, value) -> result.put(key, renderValue(value, result, macroManager))
6670
);
@@ -78,20 +82,26 @@ public Map<String, String> render(
7882
return result;
7983
}
8084

81-
private static EnvVarsProvider resolveEnvVarsProvider(@NotNull String parserId, Map<String, String> baseEnv)
85+
private EnvVarsProvider resolveEnvVarsProvider(
86+
Project project,
87+
Map<String, String> baseEnv,
88+
EnvFileEntry entry
89+
)
8290
throws EnvFileException {
83-
val parserFactory = EnvVarsProviderExtension.getParserFactoryById(parserId)
91+
val parserFactory = EnvVarsProviderExtension.getParserFactoryById(entry.getParserId())
8492
.orElseThrow(() ->
8593
EnvFileException.format(
8694
"Cannot find implementation for Environment Variables provider '%s'. " +
8795
"Deactivate, or delete entry, or enable 'Ignore missing files' setting.",
88-
parserId
96+
entry.getParserId()
8997
)
9098
);
9199

92100
EnvVarsProvider instance;
93101
try {
94-
instance = parserFactory.createProvider(baseEnv);
102+
instance = parserFactory.createProvider(baseEnv, value ->
103+
notify(project, entry, value)
104+
);
95105
} catch (Exception e) {
96106
throw new EnvFileException(e);
97107
}
@@ -100,7 +110,7 @@ private static EnvVarsProvider resolveEnvVarsProvider(@NotNull String parserId,
100110
throw EnvFileException.format(
101111
"Environment Variables provider '%s' cannot be instantiated. " +
102112
"Deactivate, or delete entry, or enable 'Ignore missing files' setting.",
103-
parserId
113+
entry.getParserId()
104114
);
105115
}
106116

@@ -124,4 +134,18 @@ private String renderValue(String template, @NotNull Map<String, String> context
124134

125135
return stage2;
126136
}
137+
138+
private void notify(Project project, EnvFileEntry entry, String content) {
139+
val notification = new Notification(NOTIFICATION_GROUP, content, NotificationType.INFORMATION);
140+
notification.setTitle(
141+
projectFileResolver.resolvePath(project, entry.getPath())
142+
.map(File::getAbsolutePath)
143+
.orElse(entry.getParserId())
144+
);
145+
notification.setSubtitle(
146+
entry.isExecutable() ? "Executing" : "Reading"
147+
);
148+
149+
Notifications.Bus.notify(notification, project);
150+
}
127151
}

src/main/resources/META-INF/plugin.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@
7979
</extensions>
8080

8181
<extensions defaultExtensionNs="com.intellij">
82+
<notificationGroup displayType="NONE" id="net.ashald.envfile"/>
8283
<fileTypeFactory implementation="net.ashald.envfile.platform.EnvFileTypeFactory"/>
8384
<applicationService serviceImplementation="net.ashald.envfile.products.idea.scala.SbtRunConfigurationExtensionManager"/>
8485
</extensions>

0 commit comments

Comments
 (0)