Skip to content

Commit

Permalink
added docs for the msbuild task (#2191)
Browse files Browse the repository at this point in the history
  • Loading branch information
majastrz authored Apr 10, 2021
1 parent 0195a3e commit 0a819e6
Show file tree
Hide file tree
Showing 2 changed files with 164 additions and 4 deletions.
164 changes: 160 additions & 4 deletions docs/cicd-with-bicep.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
# Adding Bicep to a CI/CD pipeline

## Build and Deploy with CI/CD
As your Bicep practice matures, you will want to check-in your Bicep code into source control and kick off a pipeline or workflow, which would do the following:

1. Build your Bicep file into an ARM Template
1. Deploy the generated ARM template

With the current Azure CLI 2.20 now installed in GitHub and also on Azure DevOps, Bicep CLI can be automatically triggerd by using `az bicep build` command and an explicit task to download Bicep CLI is no more needed.

The two examples below illustrates this. It assumes the following prerequisite:
The two examples below illustrate this. They assume the following prerequisites:

* The Bicep file you want to transpile and deploy is called `main.bicep` and exists in the root of the repo
* The parameters file you want to use is called `parameters.json` and exists in the root of the repo
* You are deploying the transpiled ARM Template to a resource group. Deploying to another scope like a subscription requires a different CLI command.

## GitHub Workflow
### GitHub Workflow

```yaml

Expand Down Expand Up @@ -68,7 +68,7 @@ jobs:
az account show
az deployment group create -f ./main.json -g ${{ env.AZURE_RESOURCE_GROUP }}
```
## Azure DevOps Pipeline
### Azure DevOps Pipeline
```yaml
trigger:
Expand Down Expand Up @@ -152,4 +152,160 @@ stages:
csmFile: '$(Pipeline.Workspace)/drop/main.json'
csmParametersFile: '$(Pipeline.Workspace)/drop/parameters.json'
deploymentMode: 'Incremental'
```
## Build with MSBuild
If your existing CI pipeline heavily relies on MSBuild, you can use our MSBuild task and CLI packages to compile your .bicep files into ARM templates.
This functionality relies on the following NuGet packages:
| Package Name | Description |
|:-|-|
| `Azure.Bicep.MSBuild` | Cross-platform MSBuild task to invoke the Bicep CLI to compile .bicep files into ARM templates |
| `Azure.Bicep.CommandLine.win-x64` | Bicep CLI for Windows |
| `Azure.Bicep.CommandLine.linux-x64` | Bicep CLI for Linux |
| `Azure.Bicep.CommandLine.osx-x64` | Bicep CLI for OSX |

### `Azure.Bicep.CommandLine.*` packages
When referenced in a project file via a `PackageReference`, the `Azure.Bicep.CommandLine.*` packages set the `BicepPath` property to the full path of the Bicep executable for the platform. The reference to this package may be omitted if Bicep CLI is installed through other means and the `BicepPath` environment variable or MSBuild property are set accordingly.

### `Azure.Bicep.MSBuild` package
When referenced in a project file via a `PackageReference`, the `Azure.Bicep.MSBuild` package imports the `Bicep` task used to invoke the Bicep CLI and convert its output into MSBuild errors and the `BicepCompile` target used to simplify the usage of the `Bicep` task. By default the `BicepCompile` runs after the `Build` target and will compile all `@(Bicep)` items and place the output in `$(OutputPath)` with the same file name and the `.json` extension.

The following will compile `one.bicep` and `two.bicep` files in the same directory as the project file and placed the compiled `one.json` and `two.json` in the `$(OutputPath)`.
```msbuild
<ItemGroup>
<Bicep Include="one.bicep" />
<Bicep Include="two.bicep" />
</ItemGroup>
```

You can override the output path per file using the `OutputFile` metadata on `Bicep` items. The following will recursively find all `main.bicep` files and place the compiled `.json` files in `$(OutputPath)` under a sub-directory with the same name in `$(OutputPath)`:
```msbuild
<ItemGroup>
<Bicep Include="**\main.bicep" OutputFile="$(OutputPath)\%(RecursiveDir)\%(FileName).json" />
</ItemGroup>
```

Additional customizations can be performed by setting one of the following properties in your project:
| Property Name | Default Value | Description |
|:-|:-|:-|
| `BicepCompileAfterTargets` | `Build` | Used as `AfterTargets` value for the `BicepCompile` target. Change the value to override the scheduling of the `BicepCompile` target in your project. |
| `BicepCompileDependsOn` | None | Used as `DependsOnTargets` value for the `BicepCompile` target. This can be set to targets that you want `BicepCompile` target to depend on. |
| `BicepCompileBeforeTargets` | None | Used as `BeforeTargets` value for the `BicepCompile` target. |
| `BicepOutputPath` | `$(OutputPath)` | Set this to override the default output path for the compiled ARM template. `OutputFile` metadata on `Bicep` items takes precedence over this value. |

The `Azure.Bicep.MSBuild` requires the `BicepPath` property to be set either in order to function. You may set it by referencing the appropriate `Azure.Bicep.CommandLine.*` package for your OS or manually by installing the Bicep CLI and setting the `BicepPath` environment variable or MSBuild property. The examples below assume Windows.

### SDK-based .csproj example
The following contains a default Console App SDK-based C# project file that was modified to additionally compile Bicep files into ARM templates. This type of project will work with the classic .net framework, .net core, and .net 5.

> Replace `__LATEST_VERSION__` with the latest version of the Bicep NuGet packages.

```xml
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<!-- Bicep Packages -->
<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" />
</ItemGroup>
</Project>
```

### NoTargets SDK example
The following contains a project that compiles Bicep files into ARM templates using the NoTargets SDK. This allows creation of standalone projects that compile only Bicep files.
> Replace `__LATEST_VERSION__` with the latest version of the Bicep NuGet packages.

```xml
<Project Sdk="Microsoft.Build.NoTargets">
<PropertyGroup>
<TargetFramework>net472</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"/>
</ItemGroup>
</Project>
```

### Classic .csproj example
The following contains an example of how to build Bicep files inside a classic .csproj file (not SDK-based). Only use this if the previous examples do not work for you.
> Replace `__LATEST_VERSION__` with the latest version of the Bicep NuGet packages.

```xml
<?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>{7E4E9C45-3EBE-419D-9E45-BCF7CA61961E}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>ClassicFramework</RootNamespace>
<AssemblyName>ClassicFramework</AssemblyName>
<TargetFrameworkVersion>v4.7.2</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="Bicep\main.bicep" />
</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>
```
4 changes: 4 additions & 0 deletions scripts/UploadSignedReleaseArtifacts.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ $artifacts = @(
@{
assetName = "Azure.Bicep.MSBuild.$buildVersion.nupkg";
relativePath = "Azure.Bicep.MSBuild.$buildVersion.nupkg";
},
@{
assetName = "Azure.Bicep.MSBuild.$buildVersion.snupkg";
relativePath = "Azure.Bicep.MSBuild.$buildVersion.snupkg";
}
);
zipAssets = @(
Expand Down

0 comments on commit 0a819e6

Please sign in to comment.