Azure / bicep

Bicep is a declarative language for describing and deploying Azure resources
MIT License
3.2k stars 742 forks source link

How to integrate Bicep into SFPROJ which is in classic, pre-SDK format #10685

Closed abatishchev closed 11 months ago

abatishchev commented 1 year ago

Is your feature request related to a problem? Please describe.

I'd like to include Bicep into my SFPROJ project so it would compile the bicep files into the ARM templates. Currently they're hand-coded and included into the project using <None Include="ServiceGroupRoot\**\*.json" />.

I updated packages.config:

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Azure.Bicep.CommandLine.win-x64" version="0.13.1" developmentDependency="true" />
  <package id="Azure.Bicep.MSBuild" version="0.17.1" developmentDependency="true" />
  <package id="Microsoft.VisualStudio.Azure.Fabric.MSBuild" version="1.7.9" developmentDependency="true" />
</packages>

And the project itself:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
...
  <Import Project="..\..\packages\Azure.Bicep.CommandLine.win-x64.0.13.1\build\Azure.Bicep.CommandLine.win-x64.props" Condition="Exists('..\..\packages\Azure.Bicep.CommandLine.win-x64.0.13.1\build\Azure.Bicep.CommandLine.win-x64.props')" />
  <Import Project="..\..\packages\Azure.Bicep.MSBuild.0.17.1\build\Azure.Bicep.MSBuild.props" Condition="Exists('..\..\packages\Azure.Bicep.MSBuild.0.17.1\build\Azure.Bicep.MSBuild.props')" />
...
  <PropertyGroup Label="Globals">
    <BicepPath>..\..\packages\Azure.Bicep.CommandLine.win-x64.0.13.1\tools\bicep.exe</BicepPath>
  </PropertyGroup>
...
  <ItemGroup>
    <Bicep Include="ServiceGroupRoot\Template\main.bicep" OutputFile="ServiceGroupRoot\Template\ResourceProvider.json" />
  </ItemGroup>
...
<Import Project="..\..\packages\Azure.Bicep.MSBuild.0.17.1\build\Azure.Bicep.MSBuild.targets" Condition="Exists('..\..\packages\Azure.Bicep.MSBuild.0.17.1\build\Azure.Bicep.MSBuild.targets')" />
...
</Project>

But nothing happens when I build from within VS.

Describe the solution you'd like

What might be missing in writing it up?

WhitWaldo commented 1 year ago

I would advise that instead of trying to bundle Bicep with your Service Fabric project, you instead simply build the Bicep templates in a separate solution and consider writing their ARM equivalents out to a storage blob somewhere that you can invoke from your SF service.

abatishchev commented 1 year ago

hi @WhitWaldo, This project is for a SF application (not the underlying cluster and other infra). Currently it includes the ARM template and all necessary files (what includes some additional files per the internal tooling and compliance requirements). Those which I'd like to convert to Bicep and what's important - include it into the build process. I'm investigating the latter in two directions:

  1. A separate project, e.g. Bicep.msbuildproj which is dedicated to compiling the Bicep files (and then Application.sfproj would depend on its outputs), see https://github.com/Azure/bicep/issues/10686
  2. Include it into Application.sfproj` directly (this issue)
WhitWaldo commented 1 year ago

If you find a solution, I'd be curious to know how you tackle it. Personally, I was unable to do so (given the older nature of the sfproj project file) and opted, as I said above, to simply split it out to a separate project that would deploy the artifacts to a place accessible to any other deployment or the larger SF project.

Depending on what it is you're using Bicep for, you might also consider skipping the template creation and invoking the Azure Management SDKs for the various CRUD operations directly from your service logic.

Good luck!

majastrz commented 1 year ago

@abatishchev What you're trying to do should work in theory. Are you seeing the BicepCompile target invoked in the msbuild log at all? If not, you may need to change the value of BicepCompileAfterTargets to something that works in sfproj. (Feel free to send me the binlog over Teams if you can.)

abatishchev commented 1 year ago

I updated to the latest (initially I accidentally used an older version of the command line package) and I tried again.

If I delete the output file completely then it works and recreates it.

However, if I only modify it slightly (e.g. remove the Bicep generated mark) then it does nothing, and here's what I see in the logs:

Target "BeforeBicepCompile" in file "D:\Projects\ATS-RP\packages\Azure.Bicep.MSBuild.0.17.1\build\Azure.Bicep.MSBuild.targets" from project "D:\Projects\ATS-RP\src\Application\Application.sfproj" (target "BicepCompile" depends on it):
Task "MakeDir"
Done executing task "MakeDir".
Task "Error" skipped, due to false condition; ( $(BicepPath) == '' ) was evaluated as ( ..\..\packages\Azure.Bicep.CommandLine.win-x64.0.17.1\tools\bicep.exe == '' ).
Done building target "BeforeBicepCompile" in project "Application.sfproj".
Target "BicepCompile" in file "D:\Projects\ATS-RP\packages\Azure.Bicep.MSBuild.0.17.1\build\Azure.Bicep.MSBuild.targets" from project "D:\Projects\ATS-RP\src\Application\Application.sfproj" (entry point):

**Skipping target "BicepCompile" because all output files are up-to-date with respect to the input files.**

Input files: ServiceGroupRoot\Template\main.bicep
Output files: ServiceGroupRoot\Template\ResourceProvider.json
Done building target "BicepCompile" in project "Application.sfproj".
Done Building Project "D:\Projects\ATS-RP\src\Application\Application.sfproj" (Build target(s)).
majastrz commented 11 months ago

@abatishchev I added a workaround to #11847 that should help with this as well.

majastrz commented 11 months ago

@abatishchev I added a workaround to #11847 that should help with this as well.

Never mind. The SFPROJ project system doesn't respect the AvailableItemName item group like C#, NoTarget, or others do.

majastrz commented 11 months ago

Regardless whether it's a good practice or not to include Bicep build in .sfproj, I got it to work with our MSBuild NuGet package. This was created in VS 2022 using the Service Fabric template in VS. I also added a single Stateless SF service but didn't modify any of its files.

packages.config:

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Azure.Bicep.CommandLine.win-x64" version="0.21.1" targetFramework="net472" />
  <package id="Azure.Bicep.MSBuild" version="0.21.1" targetFramework="net472" />
  <package id="Microsoft.VisualStudio.Azure.Fabric.MSBuild" version="1.7.9" targetFramework="net472" />
</packages>

Application1.sfproj:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <!-- pre-SDK projects require manual imports of package .props files at the top -->
  <Import Project="..\packages\Azure.Bicep.CommandLine.win-x64.0.21.1\build\Azure.Bicep.CommandLine.win-x64.props" Condition="Exists('..\packages\Azure.Bicep.CommandLine.win-x64.0.21.1\build\Azure.Bicep.CommandLine.win-x64.props')" />
  <Import Project="..\packages\Azure.Bicep.MSBuild.0.21.1\build\Azure.Bicep.MSBuild.props" Condition="Exists('..\packages\Azure.Bicep.MSBuild.0.21.1\build\Azure.Bicep.MSBuild.props')" />
  <Import Project="..\packages\Microsoft.VisualStudio.Azure.Fabric.MSBuild.1.7.9\build\Microsoft.VisualStudio.Azure.Fabric.Application.props" Condition="Exists('..\packages\Microsoft.VisualStudio.Azure.Fabric.MSBuild.1.7.9\build\Microsoft.VisualStudio.Azure.Fabric.Application.props')" />
  <PropertyGroup Label="Globals">
    <ProjectGuid>e8e906ac-53bf-4e39-aa50-9290c2dbcec8</ProjectGuid>
    <ProjectVersion>2.6</ProjectVersion>
    <MinToolsVersion>16.10</MinToolsVersion>
    <SupportedMSBuildNuGetPackageVersion>1.7.9</SupportedMSBuildNuGetPackageVersion>
    <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
  </PropertyGroup>
  <ItemGroup Label="ProjectConfigurations">
    <ProjectConfiguration Include="Debug|x64">
      <Configuration>Debug</Configuration>
      <Platform>x64</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|x64">
      <Configuration>Release</Configuration>
      <Platform>x64</Platform>
    </ProjectConfiguration>
  </ItemGroup>
  <ItemGroup>
    <None Include="ApplicationPackageRoot\ApplicationManifest.xml" />
    <None Include="ApplicationParameters\Cloud.xml" />
    <None Include="ApplicationParameters\Local.1Node.xml" />
    <None Include="ApplicationParameters\Local.5Node.xml" />
    <None Include="PublishProfiles\Cloud.xml" />
    <None Include="PublishProfiles\Local.1Node.xml" />
    <None Include="PublishProfiles\Local.5Node.xml" />
    <None Include="Scripts\Deploy-FabricApplication.ps1" />
    <None Include="StartupServiceParameters\Cloud.xml" />
    <None Include="StartupServiceParameters\Local.1Node.xml" />
    <None Include="StartupServiceParameters\Local.5Node.xml" />
    <None Include="StartupServices.xml" />
  </ItemGroup>
  <ItemGroup>
    <!-- 
      sfproj doesn't respect AvailableItemName
      Content forces the bicep file to be visible in VS
    -->
    <Content Include="main.bicep" />
    <Content Include="packages.config" />
  </ItemGroup>
  <ItemGroup>
    <!-- Usual way to compile Bicep files in an msbuild project -->
    <Bicep Include="main.bicep" />
  </ItemGroup>
  <ItemGroup>
    <ProjectReference Include="..\Stateless1\Stateless1.csproj" />
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.Common.targets" />
  <PropertyGroup>
    <ApplicationProjectTargetsPath>$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Service Fabric Tools\Microsoft.VisualStudio.Azure.Fabric.ApplicationProject.targets</ApplicationProjectTargetsPath>
  </PropertyGroup>
  <Import Project="$(ApplicationProjectTargetsPath)" Condition="Exists('$(ApplicationProjectTargetsPath)')" />
  <Import Project="..\packages\Microsoft.VisualStudio.Azure.Fabric.MSBuild.1.7.9\build\Microsoft.VisualStudio.Azure.Fabric.Application.targets" Condition="Exists('..\packages\Microsoft.VisualStudio.Azure.Fabric.MSBuild.1.7.9\build\Microsoft.VisualStudio.Azure.Fabric.Application.targets')" />
  <!-- pre-SDK projects require manual imports of package .targets files at the bottom -->
  <Import Project="..\packages\Azure.Bicep.MSBuild.0.21.1\build\Azure.Bicep.MSBuild.targets" Condition="Exists('..\packages\Azure.Bicep.MSBuild.0.21.1\build\Azure.Bicep.MSBuild.targets')" />
  <Target Name="ValidateMSBuildFiles" BeforeTargets="PrepareForBuild">
    <Error Condition="!Exists('..\packages\Microsoft.VisualStudio.Azure.Fabric.MSBuild.1.7.9\build\Microsoft.VisualStudio.Azure.Fabric.Application.props')" Text="Unable to find the '..\packages\Microsoft.VisualStudio.Azure.Fabric.MSBuild.1.7.9\build\Microsoft.VisualStudio.Azure.Fabric.Application.props' file. Please restore the 'Microsoft.VisualStudio.Azure.Fabric.MSBuild' Nuget package." />
    <Error Condition="!Exists('..\packages\Microsoft.VisualStudio.Azure.Fabric.MSBuild.1.7.9\build\Microsoft.VisualStudio.Azure.Fabric.Application.targets')" Text="Unable to find the '..\packages\Microsoft.VisualStudio.Azure.Fabric.MSBuild.1.7.9\build\Microsoft.VisualStudio.Azure.Fabric.Application.targets' file. Please restore the 'Microsoft.VisualStudio.Azure.Fabric.MSBuild' Nuget package." />
    <!-- 
      the conditions that are required on the top/bottom imports make it possible for the imports to silently fail
      the following checks prevent that
     -->
    <Error Condition="!Exists('..\packages\Azure.Bicep.CommandLine.win-x64.0.21.1\build\Azure.Bicep.CommandLine.win-x64.props')" Text="Unable to find the '..\packages\Azure.Bicep.CommandLine.win-x64.0.21.1\build\Azure.Bicep.CommandLine.win-x64.props' file. Please restore the 'Azure.Bicep.CommandLine.win-x64' Nuget package." />
    <Error Condition="!Exists('..\packages\Azure.Bicep.MSBuild.0.21.1\build\Azure.Bicep.MSBuild.props')" Text="Unable to find the '..\packages\Azure.Bicep.MSBuild.0.21.1\build\Azure.Bicep.MSBuild.props' file. Please restore the 'Azure.Bicep.MSBuild' Nuget package." />
    <Error Condition="!Exists('..\packages\Azure.Bicep.MSBuild.0.21.1\build\Azure.Bicep.MSBuild.targets')" Text="Unable to find the '..\packages\Azure.Bicep.MSBuild.0.21.1\build\Azure.Bicep.MSBuild.targets' file. Please restore the 'Azure.Bicep.MSBuild' Nuget package." />
  </Target>
</Project>