Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add the --pattern CLI argument for file system globbing #16456

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Bicep.Cli.E2eTests/src/local/restore.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ describe("bicep restore", () => {
it("should show error message when no input file path was specified", () => {
invokingBicepCommand("restore")
.shouldFail()
.withStderr(/The input file path was not specified/);
.withStderr(/Either the input file path or the --pattern parameter must be specified/);
});
});
41 changes: 40 additions & 1 deletion src/Bicep.Cli.IntegrationTests/BuildCommandTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using Bicep.Core.Samples;
using Bicep.Core.UnitTests;
using Bicep.Core.UnitTests.Assertions;
using Bicep.Core.UnitTests.Baselines;
using Bicep.Core.UnitTests.Mock;
using Bicep.Core.UnitTests.Registry;
using Bicep.Core.UnitTests.Utils;
Expand Down Expand Up @@ -39,7 +40,7 @@ public async Task Build_ZeroFiles_ShouldFail_WithExpectedErrorMessage()
output.Should().BeEmpty();

error.Should().NotBeEmpty();
error.Should().Contain($"The input file path was not specified");
error.Should().Contain($"Either the input file path or the --pattern parameter must be specified");
}
}

Expand Down Expand Up @@ -292,6 +293,44 @@ public async Task Build_WithOutFile_ShouldSucceed()
output.Should().BeEmpty();
}

[TestMethod]
[DataRow(false)]
[DataRow(true)]
public async Task Build_should_compile_files_matching_pattern(bool useRootPath)
{
var contents = """
output myOutput string = 'hello!'
""";

var outputPath = FileHelper.GetUniqueTestOutputPath(TestContext);
var fileResults = new[]
{
(input: "file1.bicep", expectOutput: true),
(input: "file2.bicep", expectOutput: true),
(input: "nofile.bicep", expectOutput: false)
};

foreach (var (input, _) in fileResults)
{
FileHelper.SaveResultFile(TestContext, input, contents, outputPath);
}

var (output, error, result) = await Bicep(
services => services.WithEnvironment(useRootPath ? TestEnvironment.Default : TestEnvironment.Default with { CurrentDirectory = outputPath }),
["build",
"--pattern", useRootPath ? $"{outputPath}/file*.bicep" : "file*.bicep"]);

result.Should().Be(0);
error.Should().BeEmpty();
output.Should().BeEmpty();

foreach (var (input, expectOutput) in fileResults)
{
var outputFile = Path.ChangeExtension(input, ".json");
File.Exists(Path.Combine(outputPath, outputFile)).Should().Be(expectOutput);
}
}

[TestMethod]
public async Task Build_WithNonExistentOutDir_ShouldFail_WithExpectedErrorMessage()
{
Expand Down
58 changes: 53 additions & 5 deletions src/Bicep.Cli.IntegrationTests/BuildParamsCommandTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using Bicep.Core.Extensions;
using Bicep.Core.Registry;
using Bicep.Core.Samples;
using Bicep.Core.UnitTests;
using Bicep.Core.UnitTests.Assertions;
using Bicep.Core.UnitTests.Baselines;
using Bicep.Core.UnitTests.Mock;
Expand All @@ -31,7 +32,7 @@ public class BuildParamsCommandTests : TestBase
private InvocationSettings Settings
=> new()
{
Environment = TestEnvironment.Create(
Environment = TestEnvironment.Default.WithVariables(
("stringEnvVariableName", "test"),
("intEnvVariableName", "100"),
("boolEnvironmentVariable", "true")
Expand Down Expand Up @@ -135,7 +136,7 @@ param objParam object

var settings = Settings with
{
Environment = TestEnvironment.Create(
Environment = TestEnvironment.Default.WithVariables(
("BICEP_PARAMETERS_OVERRIDES", paramsOverrides)
)
};
Expand Down Expand Up @@ -180,7 +181,7 @@ public async Task Build_params_with_default_value_override_succeeds()
""",
Path.GetDirectoryName(bicepparamsPath));

var environment = TestEnvironment.Create(("BICEP_PARAMETERS_OVERRIDES", new
var environment = TestEnvironment.Default.WithVariables(("BICEP_PARAMETERS_OVERRIDES", new
{
foo = "bar"
}.ToJson()));
Expand Down Expand Up @@ -224,7 +225,7 @@ public async Task Build_params_with_incorrect_default_value_override_fails()
""",
Path.GetDirectoryName(bicepparamsPath));

var environment = TestEnvironment.Create(("BICEP_PARAMETERS_OVERRIDES", new
var environment = TestEnvironment.Default.WithVariables(("BICEP_PARAMETERS_OVERRIDES", new
{
wrongName = "bar"
}.ToJson()));
Expand Down Expand Up @@ -262,7 +263,7 @@ param intParam int

var settings = Settings with
{
Environment = TestEnvironment.Create(
Environment = TestEnvironment.Default.WithVariables(
("BICEP_PARAMETERS_OVERRIDES", paramsOverrides)
)
};
Expand Down Expand Up @@ -542,5 +543,52 @@ param unusedParam int

result.Should().Be(0);
}

[TestMethod]
[DataRow(false)]
[DataRow(true)]
public async Task BuildParams_should_compile_files_matching_pattern(bool useRootPath)
{
var outputPath = FileHelper.GetUniqueTestOutputPath(TestContext);

FileHelper.SaveResultFile(TestContext, "main.bicep", """
param intParam int

output intOutput int = intParam
""", outputPath);
var contents = """
using 'main.bicep'

param intParam = 42
""";


var fileResults = new[]
{
(input: "file1.bicepparam", expectOutput: true),
(input: "file2.bicepparam", expectOutput: true),
(input: "nofile.bicepparam", expectOutput: false)
};

foreach (var (input, _) in fileResults)
{
FileHelper.SaveResultFile(TestContext, input, contents, outputPath);
}

var (output, error, result) = await Bicep(
services => services.WithEnvironment(useRootPath ? TestEnvironment.Default : TestEnvironment.Default with { CurrentDirectory = outputPath }),
["build-params",
"--pattern", useRootPath ? $"{outputPath}/file*.bicepparam" : "file*.bicepparam"]);

result.Should().Be(0);
error.Should().BeEmpty();
output.Should().BeEmpty();

foreach (var (input, expectOutput) in fileResults)
{
var outputFile = Path.ChangeExtension(input, ".json");
File.Exists(Path.Combine(outputPath, outputFile)).Should().Be(expectOutput);
}
}
}
}
43 changes: 42 additions & 1 deletion src/Bicep.Cli.IntegrationTests/FormatCommandTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public async Task Format_MissingInputFilePath_Fails()
{
var result = await Bicep("format");

AssertFailure(result, "The input file path was not specified");
AssertFailure(result, "Either the input file path or the --pattern parameter must be specified");
}

[TestMethod]
Expand Down Expand Up @@ -165,6 +165,47 @@ public async Task Format_SampleBicepFile_MatchesFormattedSample(DataSet dataSet)
actual.Should().Be(dataSet.Formatted);
}

[TestMethod]
[DataRow(false)]
[DataRow(true)]
public async Task Format_should_format_files_matching_pattern(bool useRootPath)
{
var unformatted = """
output myOutput string = 'hello!'
""";
var formatted = """
output myOutput string = 'hello!'

""";

var outputPath = FileHelper.GetUniqueTestOutputPath(TestContext);
var fileResults = new[]
{
(input: "file1.bicep", expectOutput: true),
(input: "file2.bicep", expectOutput: true),
(input: "nofile.bicep", expectOutput: false)
};

foreach (var (input, _) in fileResults)
{
FileHelper.SaveResultFile(TestContext, input, unformatted, outputPath);
}

var (output, error, result) = await Bicep(
services => services.WithEnvironment(useRootPath ? TestEnvironment.Default : TestEnvironment.Default with { CurrentDirectory = outputPath }),
["format",
"--pattern", useRootPath ? $"{outputPath}/file*.bicep" : "file*.bicep"]);

result.Should().Be(0);
error.Should().BeEmpty();
output.Should().BeEmpty();

foreach (var (input, expectOutput) in fileResults)
{
File.ReadAllText(Path.Combine(outputPath, input)).Should().Be(expectOutput ? formatted : unformatted);
}
}

[TestMethod]
public async Task Format_WithOutFile_WritesContentToOutFile()
{
Expand Down
Empty file.
59 changes: 33 additions & 26 deletions src/Bicep.Cli.IntegrationTests/LintCommandTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,31 +28,6 @@ namespace Bicep.Cli.IntegrationTests;
[TestClass]
public class LintCommandTests : TestBase
{
[TestMethod]
public async Task Help_should_output_lint_usage_information()
{
var (output, error, result) = await Bicep("--help");

result.Should().Be(0);
error.Should().BeEmpty();
output.Should().Contain("""
bicep lint [options] <file>
Lints a .bicep file.

Arguments:
<file> The input file

Options:
--no-restore Skips restoring external modules.
--diagnostics-format <format> Sets the format with which diagnostics are displayed. Valid values are ( Default | Sarif ).

Examples:
bicep lint file.bicep
bicep lint file.bicep --no-restore
bicep lint file.bicep --diagnostics-format sarif
""");
}

[TestMethod]
public async Task Lint_ZeroFiles_ShouldFail_WithExpectedErrorMessage()
{
Expand All @@ -64,7 +39,7 @@ public async Task Lint_ZeroFiles_ShouldFail_WithExpectedErrorMessage()
output.Should().BeEmpty();

error.Should().NotBeEmpty();
error.Should().Contain($"The input file path was not specified");
error.Should().Contain($"Either the input file path or the --pattern parameter must be specified");
}
}

Expand Down Expand Up @@ -189,6 +164,38 @@ public async Task Lint_WithEmptyBicepConfig_ShouldProduceConfigurationError()
error.Should().StartWith($"{inputFile}(1,1) : Error BCP271: Failed to parse the contents of the Bicep configuration file \"{configurationPath}\" as valid JSON: The input does not contain any JSON tokens. Expected the input to start with a valid JSON token, when isFinalBlock is true. LineNumber: 0 | BytePositionInLine: 0.");
}

[TestMethod]
[DataRow(false)]
[DataRow(true)]
public async Task Lint_should_compile_files_matching_pattern(bool useRootPath)
{
var contents = """
output myOutput string = 'hello!'
""";

var outputPath = FileHelper.GetUniqueTestOutputPath(TestContext);
var fileResults = new[]
{
(input: "file1.bicep", expectOutput: true),
(input: "file2.bicep", expectOutput: true),
(input: "nofile.bicep", expectOutput: false)
};

foreach (var (input, _) in fileResults)
{
FileHelper.SaveResultFile(TestContext, input, contents, outputPath);
}

var (output, error, result) = await Bicep(
services => services.WithEnvironment(useRootPath ? TestEnvironment.Default : TestEnvironment.Default with { CurrentDirectory = outputPath }),
["lint",
"--pattern", useRootPath ? $"{outputPath}/file*.bicep" : "file*.bicep"]);

result.Should().Be(0);
error.Should().BeEmpty();
output.Should().BeEmpty();
}

[TestMethod]
public async Task Lint_with_warnings_should_log_warnings_and_return_0_exit_code()
{
Expand Down
52 changes: 51 additions & 1 deletion src/Bicep.Cli.IntegrationTests/RestoreCommandTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public async Task Restore_ZeroFiles_ShouldFail_WithExpectedErrorMessage()
output.Should().BeEmpty();

error.Should().NotBeEmpty();
error.Should().Contain($"The input file path was not specified");
error.Should().Contain($"Either the input file path or the --pattern parameter must be specified");
}
}

Expand Down Expand Up @@ -77,6 +77,56 @@ public async Task Restore_ShouldSucceed(string testName, DataSet dataSet, bool p
}
}

[TestMethod]
[DataRow(false)]
[DataRow(true)]
public async Task Restore_should_succeed_for_files_matching_pattern(bool useRootPath)
{
var clientFactory = RegistryHelper.CreateMockRegistryClient(new RegistryHelper.RepoDescriptor("mockregistry.io", "test/foo", ["v1"]));
await RegistryHelper.PublishModuleToRegistryAsync(
new ServiceBuilder(),
clientFactory,
BicepTestConstants.FileSystem,
new("br:mockregistry.io/test/foo:1.1", """
output myOutput string = 'hello!'
""", WithSource: false));

var cacheRoot = FileHelper.GetCacheRootDirectory(TestContext);

var contents = """
module mod 'br:mockregistry.io/test/foo:1.1' = {
name: 'mod'
}
""";
var outputPath = FileHelper.GetUniqueTestOutputPath(TestContext);
var fileResults = new[]
{
(input: "file1.bicep", expectOutput: true),
(input: "file2.bicep", expectOutput: true),
(input: "nofile.bicep", expectOutput: false)
};

foreach (var (input, _) in fileResults)
{
FileHelper.SaveResultFile(TestContext, input, contents, outputPath);
}

var (output, error, result) = await Bicep(
services => services
.WithFeatureOverrides(new(CacheRootDirectory: cacheRoot, RegistryEnabled: true))
.WithContainerRegistryClientFactory(clientFactory)
.WithEnvironment(useRootPath ? TestEnvironment.Default : TestEnvironment.Default with { CurrentDirectory = outputPath }),
["restore",
"--pattern", useRootPath ? $"{outputPath}/file*.bicep" : "file*.bicep"]);

result.Should().Be(0);
error.Should().BeEmpty();
output.Should().BeEmpty();

// ensure something got restored
CachedModules.GetCachedModules(BicepTestConstants.FileSystem, cacheRoot).Should().HaveCountGreaterThan(0);
}

[TestMethod]
[EmbeddedFilesTestData(@"Files/BuildParamsCommandTests/Registry/main\.bicepparam")]
[TestCategory(BaselineHelper.BaselineTestCategory)]
Expand Down
1 change: 1 addition & 0 deletions src/Bicep.Cli.IntegrationTests/packages.lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -1698,6 +1698,7 @@
"dependencies": {
"FluentAssertions": "[7.0.0, )",
"MSTest": "[3.8.2, )",
"Moq": "[4.20.72, )",
"bicep": "[1.0.0, )"
}
},
Expand Down
Loading
Loading