快速入门:使用 MSBuild 将 Bicep 转换为 JSON
了解利用 MSBuild 将 Bicep 文件转换为 Azure 资源管理器 JSON 模板(ARM 模板)的过程。 此外,MSBuild 还可用于将 Bicep 参数文件转换为具有 NuGet 包版本 0.23.x 或更高版本的 Azure 资源管理器参数文件。 本文提供的示例演示如何使用命令行中的 MSBuild 和 C# 项目文件进行转换。 这些项目文件可用作在 MSBuild 持续集成 (CI) 管道中使用的示例。
需要以下软件的最新版本:
- Visual Studio 或 Visual Studio Code。 Visual Studio 社区版本将免费安装 .NET 6.0、.NET Core 3.1、.NET SDK、MSBuild、.NET Framework 4.8、NuGet 包管理器和 C# 编译器。 从安装程序中选择“工作负载”>“.NET 桌面开发”。 使用 Visual Studio Code 时,还需要 Bicep 和 Azure 资源管理器 (ARM) 工具的扩展
- 适用于操作系统的 PowerShell 或命令行 shell。
如果你的环境未将 nuget.org 配置为包源,则根据 nuget.config
的配置方式,你可能需要运行以下命令:
dotnet nuget add source https://api.nuget.org/v3/index.json -n nuget.org
在某些环境中,使用单个包源有助于避免具有相同 ID 和版本的包在不同源中包含不同内容而引起的问题。
对于持续集成 (CI) 管道,可以使用 MSBuild 任务和 CLI 包将 Bicep 文件和 Bicep 参数文件转换为 JSON。 此功能依赖于以下 NuGet 包:
包名称 | 说明 |
---|---|
Azure.Bicep.MSBuild | 跨平台 MSBuild 任务,用于调用 Bicep CLI,并将 Bicep 文件编译为 ARM JSON 模板。 |
Azure.Bicep.CommandLine.win-x64 | 适用于 Windows 的 Bicep CLI。 |
Azure.Bicep.CommandLine.linux-x64 | 适用于 Linux 的 Bicep CLI。 |
Azure.Bicep.CommandLine.osx-x64 | 适用于 macOS 的 Bicep CLI。 |
可以从这些页面找到最新版本。 例如:
最新的 NuGet 包版本与最新的 Bicep CLI 版本匹配。
Azure.Bicep.MSBuild
当包含在项目文件的
PackageReference
属性中时,Azure.Bicep.MSBuild
包会导入用于调用 Bicep CLI 的 Bicep 任务。<ItemGroup> <PackageReference Include="Azure.Bicep.MSBuild" Version="0.24.24" /> ... </ItemGroup>
此包将 Bicep CLI 的输出转换为 MSBuild 错误,并导入
BicepCompile
目标以简化 Bicep 任务的使用。 默认情况下,BicepCompile
在Build
目标之后运行,编译所有 @(Bicep) 项和 @(BicepParam) 项。 然后,它将输出以相同的文件名和 .json 扩展名存储到$(OutputPath)
中。以下示例显示了用于在项目文件所在的目录中编译 main.bicep 和 main.bicepparam 文件的项目文件设置,并将编译后的 main.json 和 main.parameters.json 放在
$(OutputPath)
目录中。<ItemGroup> <Bicep Include="main.bicep" /> <BicepParam Include="main.bicepparam" /> </ItemGroup>
可使用
Bicep
项的OutputFile
元数据替代每个文件的输出路径。 以下示例将以递归方式查找所有 main.bicep 文件,并将编译后的 .json 文件放在$(OutputPath)
中同名的子目录下的$(OutputPath)
中:<ItemGroup> <Bicep Include="**\main.bicep" OutputFile="$(OutputPath)\%(RecursiveDir)\%(FileName).json" /> <BicepParam Include="**\main.bicepparam" OutputFile="$(OutputPath)\%(RecursiveDir)\%(FileName).parameters.json" /> </ItemGroup>
可通过在项目中将以下属性之一设置为
PropertyGroup
来执行更多自定义:属性名称 默认值 说明 BicepCompileAfterTargets
Build
用作 BicepCompile
目标的AfterTargets
值。 更改该值以替代项目中BicepCompile
目标的计划。BicepCompileDependsOn
无 用作 BicepCompile
目标的DependsOnTargets
值。 可将此属性设置为希望BicepCompile
目标依赖的目标。BicepCompileBeforeTargets
无 用作 BicepCompile
目标的BeforeTargets
值。BicepOutputPath
$(OutputPath)
设置此属性以替代编译的 ARM 模板的默认输出路径。 Bicep
项上的OutputFile
元数据优先于此值。若要运行
Azure.Bicep.MSBuild
,必须设置名为BicepPath
的环境变量。 有关如何配置BicepPath
,请查看下一个项目符号项。Azure.Bicep.CommandLine
Azure.Bicep.CommandLine.*
包适用于 Windows、Linux 和 macOS。 以下示例引用适用于 Windows 的包。<ItemGroup> <PackageReference Include="Azure.Bicep.CommandLine.win-x64" Version="__LATEST_VERSION__" /> ... </ItemGroup>
在项目文件中引用时,
Azure.Bicep.CommandLine.*
包将BicepPath
属性自动设置为该平台的 Bicep 可执行文件的完整路径。 如果通过其他方式安装 Bicep CLI,则可以省略对此包的引用。 在这种情况下,可以配置一个名为BicepPath
的环境变量或将BicepPath
添加到PropertyGroup
,而不是引用Azure.Bicep.Commandline
包,例如在 Windows 上:<PropertyGroup> <BicepPath>c:\users\john\.Azure\bin\bicep.exe</BicepPath> ... </PropertyGroup>
在 Linux 上:
<PropertyGroup> <BicepPath>/usr/local/bin/bicep</BicepPath> ... </PropertyGroup>
以下示例演示如何配置 C# 控制台应用程序项目文件,以便将 Bicep 文件和 Bicep 参数文件转换为 JSON。 将以下示例中的 __LATEST_VERSION__
替换为最新版本的 Bicep NuGet 包。 要查找最新版本,请参阅 MSBuild 任务和 Bicep 包。
.NET Core 3.1 和 .NET 6 示例类似。 但 .NET 6 使用不同格式的 Program.cs 文件。 有关详细信息,请参阅 .NET 6 C# 控制台应用模板生成顶级语句。
.NET 6
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net6.0</TargetFramework> <RootNamespace>net6-sdk-project-name</RootNamespace> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> </PropertyGroup> <ItemGroup> <PackageReference Include="Azure.Bicep.CommandLine.win-x64" Version="__LATEST_VERSION__" /> <PackageReference Include="Azure.Bicep.MSBuild" Version="__LATEST_VERSION__" /> </ItemGroup> <ItemGroup> <Bicep Include="**\main.bicep" OutputFile="$(OutputPath)\%(RecursiveDir)\%(FileName).json" /> <BicepParam Include="**\main.bicepparam" OutputFile="$(OutputPath)\%(RecursiveDir)\%(FileName).parameters.json" /> </ItemGroup> </Project>
RootNamespace
属性包含占位符值。 创建项目文件时,该值与项目的名称匹配。
.NET Core 3.1
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>netcoreapp3.1</TargetFramework> </PropertyGroup> <ItemGroup> <PackageReference Include="Azure.Bicep.CommandLine.win-x64" Version="__LATEST_VERSION__" /> <PackageReference Include="Azure.Bicep.MSBuild" Version="__LATEST_VERSION__" /> </ItemGroup> <ItemGroup> <Bicep Include="**\main.bicep" OutputFile="$(OutputPath)\%(RecursiveDir)\%(FileName).json" /> <BicepParam Include="**\main.bicepparam" OutputFile="$(OutputPath)\%(RecursiveDir)\%(FileName).parameters.json" /> </ItemGroup> </Project>
Microsoft.Build.NoTargets MSBuild 项目 SDK 允许项目树所有者定义不编译程序集的项目。 利用此 SDK 可创建仅编译 Bicep 文件的独立项目。
<Project Sdk="Microsoft.Build.NoTargets/__LATEST_MICROSOFT.BUILD.NOTARGETS.VERSION__">
<PropertyGroup>
<TargetFramework>net48</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Azure.Bicep.CommandLine.win-x64" Version="__LATEST_VERSION__" />
<PackageReference Include="Azure.Bicep.MSBuild" Version="__LATEST_VERSION__" />
</ItemGroup>
<ItemGroup>
<Bicep Include="main.bicep"/>
<BicepParam Include="main.bicepparam"/>
</ItemGroup>
</Project>
可在 https://www.nuget.org/packages/Microsoft.Build.NoTargets 找到最新的 Microsoft.Build.NoTargets
版本。 在 Microsoft.Build.NoTargets 中,请指定版本,如 Microsoft.Build.NoTargets/3.7.56
。
<Project Sdk="Microsoft.Build.NoTargets/3.7.56">
...
</Project>
仅当前面的示例不适用时,才使用经典示例。 在此示例中,ProjectGuid
、RootNamespace
和 AssemblyName
属性包含占位符值。 创建项目文件时,将创建唯一 GUID,并且名称值与项目的名称匹配。
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{11111111-1111-1111-1111-111111111111}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>ClassicFramework</RootNamespace>
<AssemblyName>ClassicFramework</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<Bicep Include="main.bicep" />
<BicepParam Include="main.bicepparam" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Azure.Bicep.CommandLine.win-x64">
<Version>__LATEST_VERSION__</Version>
</PackageReference>
<PackageReference Include="Azure.Bicep.MSBuild">
<Version>__LATEST_VERSION__</Version>
</PackageReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
这些示例演示如何使用 MSBuild 将 Bicep 文件和 Bicep 参数文件转换为 JSON。 首先为 .NET、.NET Core 3.1 或经典框架创建项目文件。 然后,在运行 MSBuild 之前生成 Bicep 文件和 Bicep 参数文件。
使用 dotnet CLI 在 .NET 中生成项目。
打开 Visual Studio Code 并选择“终端”>“新建终端”以启动 PowerShell 会话。
创建名为 msBuildDemo 的目录并转到该目录。 此示例使用 C:\msBuildDemo。
Set-Location -Path C:\ New-Item -Name .\msBuildDemo -ItemType Directory Set-Location -Path .\msBuildDemo
运行
dotnet
命令以使用 .NET 6 框架创建新控制台。dotnet new console --framework net6.0
该命令使用与目录同名的项目文件 msBuildDemo.csproj。 若要详细了解如何从 Visual Studio Code 创建控制台应用程序,请参阅教程。
使用编辑器打开 msBuildDemo.csproj,将内容替换为 .NET 6 或 NoTargets SDK 示例,并将
__LATEST_VERSION__
替换为最新版本的 Bicep NuGet 包。保存文件。
需要将 Bicep 文件和 BicepParam 文件转换为 JSON。
在项目文件所在的文件夹中创建 main.bicep 文件,例如:C:\msBuildDemo 目录,内容如下:
@allowed([ 'Premium_LRS' 'Premium_ZRS' 'Standard_GRS' 'Standard_GZRS' 'Standard_LRS' 'Standard_RAGRS' 'Standard_RAGZRS' 'Standard_ZRS' ]) @description('Storage account type.') param storageAccountType string = 'Standard_LRS' @description('Location for all resources.') param location string = resourceGroup().location var storageAccountName = 'storage${uniqueString(resourceGroup().id)}' resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = { name: storageAccountName location: location sku: { name: storageAccountType } kind: 'StorageV2' } output storageAccountNameOutput string = storageAccount.name
在 C:\msBuildDemo 目录中创建 main.bicepparam 文件,其中包含以下内容:
using './main.bicep' param prefix = '{prefix}'
将
{prefix}
替换为用作存储帐户名称前缀的字符串值。
运行 MSBuild,将 Bicep 文件和 Bicep 参数文件转换为 JSON。
打开 Visual Studio Code 终端会话。
在 PowerShell 会话中,转到包含项目文件的文件夹。 例如,C:\msBuildDemo 目录。
运行 MSBuild。
MSBuild.exe -restore .\msBuildDemo.csproj
在初始生成期间,
restore
参数创建编译 Bicep 文件所需的依赖项。 在初始生成后,该参数是可选的。使用 .NET Core:
dotnet build .\msBuildDemo.csproj
或
dotnet restore .\msBuildDemo.csproj
转到输出目录,并打开应类似于以下示例的 main.json 文件。
MSBuild 基于 SDK 或框架版本创建输出目录:
- .NET 6:\bin\Debug\net6.0
- .NET Core 3.1:\bin\Debug\netcoreapp3.1
- NoTargets SDK:\bin\Debug\net48
- 经典框架:\bin\Debug
{ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "metadata": { "_generator": { "name": "bicep", "version": "0.8.9.13224", "templateHash": "12345678901234567890" } }, "parameters": { "storageAccountType": { "type": "string", "defaultValue": "Standard_LRS", "metadata": { "description": "Storage account type." }, "allowedValues": [ "Premium_LRS", "Premium_ZRS", "Standard_GRS", "Standard_GZRS", "Standard_LRS", "Standard_RAGRS", "Standard_RAGZRS", "Standard_ZRS" ] }, "location": { "type": "string", "defaultValue": "[resourceGroup().location]", "metadata": { "description": "Location for all resources." } } }, "variables": { "storageAccountName": "[format('storage{0}', uniqueString(resourceGroup().id))]" }, "resources": [ { "type": "Microsoft.Storage/storageAccounts", "apiVersion": "2022-05-01", "name": "[variables('storageAccountName')]", "location": "[parameters('location')]", "sku": { "name": "[parameters('storageAccountType')]" }, "kind": "StorageV2" } ], "outputs": { "storageAccountNameOutput": { "type": "string", "value": "[variables('storageAccountName')]" } } }
main.parameters.json 文件应如下所示:
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"prefix": {
"value": "mystore"
}
}
}
如果进行更改或想要重新运行生成,请删除输出目录,以便可以创建新文件。
完成对文件的操作后,请删除目录。 在本示例中,请删除 C:\msBuildDemo。
Remove-Item -Path "C:\msBuildDemo" -Recurse
- 有关 MSBuild 的详细信息,请参阅 MSBuild 参考和 .NET 项目文件。
- 若要详细了解 MSBuild 属性、项、目标和任务,请参阅 MSBuild 概念。
- 有关 .NET CLI 的详细信息,请参阅 .NET CLI 概述。