From edae01319ec5a913cef3224acc45448613de0739 Mon Sep 17 00:00:00 2001 From: Engin Polat Date: Fri, 8 Nov 2024 19:03:30 -0800 Subject: [PATCH] allow `using none` statements in bicepparam files at `build-params` command (#15107) When + there are multiple projects with a very similar infrastructure needs (usually encountered in software shops) + there are multiple layers in the same project with very similar infrastructure needs (usually encountered in multi-tenant softwares) There should be multiple `.bicep` files (per project, per layer, etc.) and multiple `.bicepparam` files pairing with `.bicep` files (with `using {filename}.bicep` statements in `.bicepparam` files) When `az deployment group create --resource-group $rgname --name $rgname --template-file ./main.bicep --parameters ./main.bicepparam` command executed, `az cli` downstreams the parameters to `bicep build-params` command. Since the `.bicep` and `.bicepparam` files are paired with the `using` statement in `.bicepparam` file, it's not possible to re-use the same `.bicepparam` file with multiple deployments. This PR relaxes the check in the `build-params` command that requires the `using` statement in the `.bicepparam` file points to the same `.bicep` file as the `build-params` command arguments So, if the `.bicepparam` file has a `using none` statement, it'll be possible to use the same `.bicepparam` file in multiple deployments. --- ## Testing the PR > git worktree add /tmp/bicep-allow-using-none polatengin/allow-using-none-statements-build-params ```bicep // main.bicep param bar string ``` ```bicep // main.bicepparam using none param bar = 'foo' ``` When you run the following command; ```bash dotnet run --project src/Bicep.Cli/Bicep.Cli.csproj -- build-params ./main.bicepparam --bicep-file ./main.bicep --stdout ``` It fails with the following error message; `Bicep file ./main.bicep provided with --bicep-file can only be used if the Bicep parameters "using" declaration refers to a Bicep file on disk.` With the changes in this PR, same command runs successfully and builds the `main.bicepparam` file ### BuildParamsCommandTests I also added a test (https://github.com/Azure/bicep/pull/15107/files#diff-30f70729cbd5bcbfb69d4edd8ff3fa9bee94690e92f5e3e86ac9a7eb98b3f550R431) to ensure the `build-params` command successfully builds given `.bicepparam` file when there is a `using none` statement instead of a `using {filename}.bicep` statement in the `.bicepparam` file. --- ###### Microsoft Reviewers: [Open in CodeFlow](https://microsoft.github.io/open-pr/?codeflow=https://github.com/Azure/bicep/pull/15107) --- .../BuildParamsCommandTests.cs | 26 +++++++++++++++++++ src/Bicep.Cli/Commands/BuildParamsCommand.cs | 17 +++++++----- 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/src/Bicep.Cli.IntegrationTests/BuildParamsCommandTests.cs b/src/Bicep.Cli.IntegrationTests/BuildParamsCommandTests.cs index 9f6ce57a997..25e34542c5e 100644 --- a/src/Bicep.Cli.IntegrationTests/BuildParamsCommandTests.cs +++ b/src/Bicep.Cli.IntegrationTests/BuildParamsCommandTests.cs @@ -428,6 +428,32 @@ public async Task Build_params_returns_intuitive_error_if_invoked_with_bicep_fil result.Should().Fail().And.HaveStderrMatch($"Bicep file * provided with --bicep-file can only be used if the Bicep parameters \"using\" declaration refers to a Bicep file on disk.*"); } + [TestMethod] + [TestCategory(BaselineHelper.BaselineTestCategory)] + public async Task Build_params_works_with_using_none() + { + var outputPath = FileHelper.GetUniqueTestOutputPath(TestContext); + + var bicepFile = FileHelper.SaveResultFile(TestContext, "main.bicep", @" + param unusedParam int + ", outputPath); + + var inputFile = FileHelper.SaveResultFile(TestContext, "main.bicepparam", @" + using none + + param unusedParam = 3 + ", outputPath); + + var (output, error, result) = await Bicep(["build-params", inputFile, "--bicep-file", bicepFile]); + + var expectedOutputFile = FileHelper.GetResultFilePath(TestContext, "main.json", outputPath); + + File.Exists(expectedOutputFile).Should().BeTrue(); + output.Should().BeEmpty(); + error.Should().BeEmpty(); + result.Should().Be(0); + } + [TestMethod] [EmbeddedFilesTestData(@"Files/BuildParamsCommandTests/Registry/main\.bicepparam")] [TestCategory(BaselineHelper.BaselineTestCategory)] diff --git a/src/Bicep.Cli/Commands/BuildParamsCommand.cs b/src/Bicep.Cli/Commands/BuildParamsCommand.cs index d5db02bfb42..ddad2b83f3e 100644 --- a/src/Bicep.Cli/Commands/BuildParamsCommand.cs +++ b/src/Bicep.Cli/Commands/BuildParamsCommand.cs @@ -63,14 +63,17 @@ public async Task RunAsync(BuildParamsArguments args) if (bicepFileUri is not null && compilation.GetEntrypointSemanticModel().Root.TryGetBicepFileSemanticModelViaUsing().IsSuccess(out var usingModel)) { - if (usingModel is not SemanticModel bicepSemanticModel) + if (usingModel is not EmptySemanticModel) { - throw new CommandLineException($"Bicep file {bicepFileUri.LocalPath} provided with --bicep-file can only be used if the Bicep parameters \"using\" declaration refers to a Bicep file on disk."); - } - - if (!bicepSemanticModel.Root.FileUri.Equals(bicepFileUri)) - { - throw new CommandLineException($"Bicep file {bicepFileUri.LocalPath} provided with --bicep-file option doesn't match the Bicep file {bicepSemanticModel.Root.Name} referenced by the \"using\" declaration in the parameters file."); + if (usingModel is not SemanticModel bicepSemanticModel) + { + throw new CommandLineException($"Bicep file {bicepFileUri.LocalPath} provided with --bicep-file can only be used if the Bicep parameters \"using\" declaration refers to a Bicep file on disk."); + } + + if (!bicepSemanticModel.Root.FileUri.Equals(bicepFileUri)) + { + throw new CommandLineException($"Bicep file {bicepFileUri.LocalPath} provided with --bicep-file option doesn't match the Bicep file {bicepSemanticModel.Root.Name} referenced by the \"using\" declaration in the parameters file."); + } } }