Skip to content

Commit

Permalink
Add trace log message when failing to find Env Var (#13777)
Browse files Browse the repository at this point in the history
Fixes #13100

If verbose is set to true in bicepconfig.json, bicep now logs the names
of all available environment variables when function
readEnvironmentVariable fails to find the variable specified. This
should hopefully help troubleshoot errors related to this function.

Example of output before:

![image](https://github.com/Azure/bicep/assets/5576847/fcdf716d-458e-4915-a07f-68607b5cd0f6)

Example of output after:

![image](https://github.com/Azure/bicep/assets/5576847/b5c1b7e3-6209-43ce-ac07-a19acd68ba60)

## Contributing a feature

* [x] I have opened a new issue for the proposal, or commented on an
existing one, and ensured that the Bicep maintainers are good with the
design of the feature being implemented
* [x] I have included "Fixes #{issue_number}" in the PR description, so
GitHub can link to the issue and close it when the PR is merged
* [x] I have appropriate test coverage of my new feature
###### Microsoft Reviewers: [Open in
CodeFlow](https://microsoft.github.io/open-pr/?codeflow=https://github.com/Azure/bicep/pull/13777)
  • Loading branch information
SimonWahlin committed Jun 12, 2024
1 parent d089f3a commit 5f64182
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 3 deletions.
30 changes: 29 additions & 1 deletion src/Bicep.Core.IntegrationTests/ParameterFileTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,37 @@ public void Parameters_file_cannot_reference_non_existing_env_variable()

result.ExcludingLinterDiagnostics().Should().HaveDiagnostics(new[]{
("BCP338", DiagnosticLevel.Error,
"Failed to evaluate parameter \"stringEnvVariable\": Environment variable does not exist, and no default value set")});
"Failed to evaluate parameter \"fromEnv\": Environment variable \"stringEnvVariable\" does not exist, and no default value set.")});
}

[TestMethod]
public void Parameters_file_cannot_reference_non_existing_env_variable_verbose()
{
var result = CompilationHelper.CompileParams(
("bicepconfig.json", """
{
"analyzers": {
"core": {
"rules": {
},
"verbose": true
}
}
}
"""),
("parameters.bicepparam", @"
using 'foo.bicep'
param fromEnv=readEnvironmentVariable('stringEnvVariable')
"),
("foo.bicep", @"param fromEnv string"));

result.ExcludingLinterDiagnostics().Should().HaveDiagnostics(new[]{
("BCP338", DiagnosticLevel.Error,
"Failed to evaluate parameter \"fromEnv\": Environment variable \"stringEnvVariable\" does not exist, and no default value set."),
("Bicepparam ReadEnvironmentVariable function", DiagnosticLevel.Info,
"Available environment variables are: "
)});
}
[TestMethod]
public void Parameters_file_can_use_variables()
{
Expand Down
3 changes: 3 additions & 0 deletions src/Bicep.Core.UnitTests/Utils/TestEnvironment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,7 @@ public static IEnvironment Create(params (string key, string? value)[] variables

public string? GetVariable(string variable)
=> variables.TryGetValue(variable, out var value) ? value : null;

public IEnumerable<string> GetVariableNames()
=> variables.Keys;
}
28 changes: 26 additions & 2 deletions src/Bicep.Core/Semantics/Namespaces/SystemNamespaceType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@
using Bicep.Core.Features;
using Bicep.Core.FileSystem;
using Bicep.Core.Intermediate;
using Bicep.Core.Analyzers.Linter;
using Bicep.Core.Modules;
using Bicep.Core.Navigation;
using Bicep.Core.Parsing;
using Bicep.Core.Syntax;
using Bicep.Core.Text;
using Bicep.Core.TypeSystem;
using Bicep.Core.TypeSystem.Providers;
using Bicep.Core.TypeSystem.Types;
Expand Down Expand Up @@ -1213,9 +1215,31 @@ private static FunctionResult ReadEnvironmentVariableResultBuilder(SemanticModel
}
else
{
var envVariableNames = model.Environment.GetVariableNames();
var suggestion = SpellChecker.GetSpellingSuggestion(envVariableName, envVariableNames);
if (suggestion != null)
{
suggestion = $" Did you mean \"{suggestion}\"?";
}
//log available environment variables if verbose logging is enabled
if (model.Configuration.Analyzers.GetValue(LinterAnalyzer.LinterEnabledSetting, false) && model.Configuration.Analyzers.GetValue(LinterAnalyzer.LinterVerboseSetting, false)) {
diagnostics.Write(
new Diagnostic(
arguments[0].Span,
DiagnosticLevel.Info,
"Bicepparam ReadEnvironmentVariable function",
$"Available environment variables are: { string.Join(", ", envVariableNames) }",
null)
);
}

//error to fail the build-param with clear message of the missing env var name
return new(ErrorType.Create(DiagnosticBuilder.ForPosition(arguments[0]).FailedToEvaluateParameter(envVariableName,
"Environment variable does not exist, and no default value set")));
var paramAssignmentDefinition = model.Root.ParameterAssignments.Where(
p => p.DeclaringParameterAssignment.Value.Span.Position == functionCall.Span.Position
).FirstOrDefault();
var paramName = paramAssignmentDefinition?.Name ?? "";
return new(ErrorType.Create(DiagnosticBuilder.ForPosition(arguments[0]).FailedToEvaluateParameter(paramName,
$"Environment variable \"{envVariableName}\" does not exist, and no default value set.{ suggestion }")));
}
}
return new(TypeFactory.CreateStringLiteralType(envVariableValue),
Expand Down
3 changes: 3 additions & 0 deletions src/Bicep.Core/Utils/Environment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,7 @@ public class Environment : IEnvironment
{
public string? GetVariable(string variable)
=> System.Environment.GetEnvironmentVariable(variable);

public IEnumerable<string> GetVariableNames()
=> System.Environment.GetEnvironmentVariables().Keys.OfType<string>();
}
2 changes: 2 additions & 0 deletions src/Bicep.Core/Utils/IEnvironment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@ namespace Bicep.Core.Utils;
public interface IEnvironment
{
string? GetVariable(string variable);

IEnumerable<string> GetVariableNames();
}

0 comments on commit 5f64182

Please sign in to comment.