Azure / azure-functions-vs-build-sdk

MSBuild task for Azure Functions
MIT License
96 stars 65 forks source link

Unable to generate nuget package when using nuget "Microsoft.NET.Sdk.Functions" in a library project #110

Open SimonLuckenuik opened 7 years ago

SimonLuckenuik commented 7 years ago

Hi, When generating the nuget package for a project which references <PackageReference Include="Microsoft.NET.Sdk.Functions" Version="1.0.2" />, the packaging fails with error: C:\Program Files\dotnet\sdk\2.0.0\Sdks\NuGet.Build.Tasks.Pack\buildCrossTargeting\NuGet.Build.Tasks.Pack.targets(141,5): error : The file 'c:\users\<user>\documents\visual studio 2017\Projects\AzFuncExtensions\AzFuncExtensions\bin\Debug\net461\AzFuncExtensions.dll' to be packed was not found on disk., since it includes some MsBuild targets which is moving DLLs in the bin subfolder.

My goal here was to include a nuget package which references all the expected dependencies currently supported by the Functions runtime (the beta versions of WebJobs for example), without having to reference the specific nuget packages directly. This will allow me to create a classic class library aligned with the Functions runtime that I can use in my pre-compiled functions, and distribute it as a nuget package.

That experience triggered sevaral comments: 1) The current description of the nuget package is: Package Description, which isn't really helpful. 2) From the name I was expecting that nuget to be what I was looking for. Maybe something including Build or Task or MsBuild? 3) There is currently no easy way to align our project nugets with the Function Runtime expected versions (except going to the github repo for webjobs and looking at the packages.config and web.config to figure out the redirects). 4) It would be nice to have a compile time warning if my nuget versions are not aligned with the Functions runtime. Currently, I have to execute my code with the CLI to figure this out. 5) I do now understand that this "Microsoft.NET.Sdk.Functions" is meant to be referenced from the pre-compiled assembly only to enable proper debugging scenarios from visual studio with the AzFunc CLI, but I do believe that what I am trying to accomplish will be done by other developers. Currently, I have to explicitly add pre-release nugets in my project (Include="Microsoft.Azure.WebJobs" Version="2.1.0-beta1"), at the next release of the runtime, I guess I will need to go upgrade manually that version to make sure I am aligned 6) It looks strange to have a non-beta nuget to depend on beta nuget... Are there any plans to have the webjobs stuff out of beta?

Project to reproduce the problem: AzFuncExtensions.csproj:

<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFrameworks>net461</TargetFrameworks>
    <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.NET.Sdk.Functions" Version="1.0.2" />
  </ItemGroup>
</Project>

The project includes a simple class:

using Microsoft.Azure.WebJobs.Host;

namespace AzFuncExtensions
{
    public static class TraceWriterExtensions
    {
        public static void LogTodo(this TraceWriter writer)
        {
            writer.Error("TODO");
        }
    }
}
espray commented 6 years ago

I am having the same issue creating a nuget when proj reference Microsoft.NET.Sdk.Functions

neiltaylormade commented 6 years ago

This is causing me headaches too, has anyone been able to get to the bottom of this?

aanttila commented 6 years ago

I'm having a similar issue, but with a different "warning" while referencing a newer version of the package (1.0.7):

C:\Users\aanttila\.nuget\packages\microsoft.net.sdk.functions\1.0.7\build\netstandard1.0\Microsoft.NET.Sdk.Functions.Build.targets(32,5): warning : [C:\SomeFolder\SomeProject.csproj]

The end result is that I can't create a NuGet package that references the Functions SDK, so we can't package some of our code the way we'd like to.

oluatte commented 6 years ago

+1

We really need this to be able to create and consume some shared code in a large functions implementation. Any updates?

holgerleichsenring commented 6 years ago

+1

Same here. Is there any workaround for generating packages even when it doesn't work with Visual Studio out-of-the-box?

Tazmainiandevil commented 5 years ago

As a work around you could create a nuspec file and include the additional bin folder image Then use the nuget command line to pack the file e.g. nuget pack Useful.Azure.Functions.Dependency.Injection.nuspec

MuhammadBilalYar commented 5 years ago

+1 same issue.

Wilou1428 commented 5 years ago

Could it be that Functions are not intended to be packaged into NuGet packages? https://blogs.technet.microsoft.com/livedevopsinjapan/2017/09/12/build-and-deploy-azure-functions-without-using-visual-studio-2017/

ysnikitin commented 5 years ago

+1

Does anyone have any solutions?

pragnagopa commented 5 years ago

@ahmelsayed / @soninaren - Is this scenario supported?

MuhammadBilalYar commented 5 years ago

Simply, I added .nuspec (in my case it's LogMetrics) file with below content in the my source project

<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
    <metadata>
        <id>AzureFunctions</id>
        <version>1.0.0.0</version>
        <title>LogMetrics</title>
        <authors>Muhammad Bilal Yar</authors>
        <owners>Muhammad Bilal Yar</owners>
        <requireLicenseAcceptance>false</requireLicenseAcceptance>
        <description>Azure Functions</description>
        <copyright>copyright</copyright>
        <tags>AzureFunctions</tags>
    </metadata>
    <files>
        <!--<file src="$OutputPath$"                                    target="\" />-->
        <file src="\bin\Release\" target="\" />
    </files>
</package>

Then pass LogMetrics.nupac file path to Nuget Pack task on Azure DevOps. image It's works for me.

MuhammadBilalYar commented 5 years ago

An alternate solution that i am using is

  1. Add Nuget. exe and NuGet.targets in source project
  2. Than add .nuspec file
  3. at last, add Post Build event, below is my post build evernt script
    <Import Project="..\.nuget\NuGet.targets" />
    <Target Name="CreateNugetPackage">
    <MakeDir Directories="$(OutDir)OctopusPackages">
      <Output PropertyName="OctopusPackagesPath" TaskParameter="DirectoriesCreated">
      </Output>
    </MakeDir>
    <Message Text="Creating NuGet package..." />
    <Exec Command="..\.nuget\nuget pack $(ProjectPath) -NoPackageAnalysis -p OutputPath=$(OutDir) -OutputDirectory $(OutDir)OctopusPackages">
    </Exec>
    </Target>
    <Target Name="AfterBuild" DependsOnTargets="CreateNugetPackage;">
    <Message Text="AfterBuild in = $(ProjectName) complete!" />
    </Target>
ysnikitin commented 5 years ago

Simply, I added .nuspec (in my case it's LogMetrics) file with below content in the my source project

<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
    <metadata>
        <id>AzureFunctions</id>
        <version>1.0.0.0</version>
        <title>LogMetrics</title>
        <authors>Muhammad Bilal Yar</authors>
        <owners>Muhammad Bilal Yar</owners>
        <requireLicenseAcceptance>false</requireLicenseAcceptance>
        <description>Azure Functions</description>
        <copyright>copyright</copyright>
        <tags>AzureFunctions</tags>
    </metadata>
    <files>
        <!--<file src="$OutputPath$"                                    target="\" />-->
        <file src="\bin\Release\" target="\" />
    </files>
</package>

Then pass LogMetrics.nupac file path to Nuget Pack task on Azure DevOps. image It's works for me.

It seems to work only with the Nuget CLI, getting this to work with dotnet CLI is problematic. The following instructions do not seem to work:

https://docs.microsoft.com/en-us/nuget/reference/msbuild-targets#packing-using-a-nuspec

ColbyTresness commented 5 years ago

@soninaren to take a look

jeffputz commented 5 years ago

This is a pretty ancient issue, but it's still a problem. It makes sense to want to publish function classes as a NuGet library, and it's pretty weird that it doesn't work.

fauve- commented 4 years ago

Hi, I'm running into this issue also. Has there been any movement on it?

vdurante commented 4 years ago

Still a problem...

vijayrkn commented 4 years ago

Is the intent here to add functions with the references to a NuGet package and use this NuGet package in other function projects?

If so, why not package using a simple NetStandard class library project?

e.g: You can put all the cs files under the resources folder and add all the required references. when this project gets packaged, it will include the functions content and references.

Packaging app:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Azure.WebJobs.Extensions.CosmosDB" Version="3.0.5" />
  </ItemGroup>

  <ItemGroup>
    <Content Include="Resources\**">
      <Pack>true</Pack>
      <PackagePath>/contentFiles/cs/netcoreapp3.1</PackagePath>
    </Content>
  </ItemGroup>

  <ItemGroup>
    <Compile Remove="Resources\**" />
  </ItemGroup>

</Project>

Consuming Function app. ClassLibrary1 package will bring in the content and references.


<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <AzureFunctionsVersion>v3</AzureFunctionsVersion>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="ClassLibrary1" Version="1.0.0" />
    <PackageReference Include="Microsoft.NET.Sdk.Functions" Version="3.0.9" />
  </ItemGroup>
  <ItemGroup>
    <None Update="host.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
    <None Update="local.settings.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <CopyToPublishDirectory>Never</CopyToPublishDirectory>
    </None>
  </ItemGroup>
</Project>
SimonLuckenuik commented 4 years ago

The goal of the initial request was to be able to develop code in libraries which are using versions exactly aligned with the Functions SDK versions, to prevent using versions which are too new vs the Azure Functions runtime. For example, back when the issue was raised, pointing to the wrong version of the Azure Storage library would cause Azure Functions to break. By adding a reference to Microsoft.NET.Sdk.Functions we are sure that our versions are aligned. Keep in mind that your sample code where everything is in the same project is not representative of how people work. For example, if I have code to share between the Azure Functions project and lets say an ASPNET core project, I would use another library in which I want to have the proper dependencies required by Az Function

If not using that Microsoft.NET.Sdk.Functions library which also includes the build step required to generate the configuration files, maybe another package with only the dependencies could be created in nuget so that it can be linked from other libraries? For example: Microsoft.NET.Sdk.Functions.Dependencies or whatever.

vijayrkn commented 4 years ago

@SimonLuckenuik - Thanks for the quick response and explanation. I see your point. In the latest 3.0.9 version of the sdk, I have removed the code where publish was overriding pack.

https://github.com/Azure/azure-functions-vs-build-sdk/commit/0992e21cc695c18b08bcf9de22ca0dc2dcab9713#diff-60eb2d9d1ecbc014c8c0a62346773539L20-L35

Even though this is removed, one of the dependent packages block the pack gen for Azure Sdk functions. So don't think this is resolved yet.

Essentially you are looking for a way to replicate this dependency graph (below) without the build generation capabilities: https://github.com/Azure/azure-functions-vs-build-sdk/blob/v3.x/src/Microsoft.NET.Sdk.Functions/Microsoft.NET.Sdk.Functions.csproj#L72-L78

Adding @fabiocav to hear his thoughts on this.

SimonLuckenuik commented 4 years ago

@vijayrkn, exactly for the dependency graph you are referring to, that would do the trick. Currently, in order to be aligned we need to visit the complete graph for each of the dependencies listed and make sure we have the exact same versions.

With a package with the dependencies, it would allow us to simply refer to that one and any conflict for mismatching versions would be flagged by nuget. For example, if I would reference directly the nuget for the lastest Newtonsoft.Json v12 along with the new Microsoft.NET.Sdk.Functions.Dependencies, I would get a nuget warning directly in visual studio if I remember well.

You could even use Microsoft.NET.Sdk.Functions.Dependencies directly from Microsoft.NET.Sdk.Functions as well, so both your team and the developers would depend on the exact same package.

vijayrkn commented 4 years ago

You could even use Microsoft.NET.Sdk.Functions.Dependencies directly from Microsoft.NET.Sdk.Functions as well, so both your team and the developers would depend on the exact same package.

Thanks for the input. Shouldn't be hard to implement but lets see what @fabiocav thinks about this approach.

Alex-Sob commented 4 years ago

If you're creating a shared library, the workaround could be to remove reference to Microsoft.NET.Sdk.Functions and instead reference some packages that Microsoft.NET.Sdk.Functions depends on. For example, I resolved this by replacing it with a reference to Microsoft.Azure.WebJobs.Extensions.Http that our library actually depends on.

klenium commented 4 years ago

@Alex-Sob Thank you so much, with that step I'm able to generate the package.

Bygdrift commented 2 years ago

It would be nice if it was possible to reference this package - just tried version 4.1.0 without luck.

cieciurm commented 2 years ago

I am currently working on a library shared across Azure Functions projects.

Instead of having a project referencing Microsoft.NET.Sdk.Functions you could have a .NET Standard library referencing SDK's dependencies:

And keep the shared code in this project (it would be a regular class library). This project can be packaged (using dotnet pack) and distributed via NuGet.

Then you could reference your shared library in the executable project which is the Function App itself (referencing Microsoft.NET.Sdk.Functions and having the Azure Functions icon).

danny-boy-online commented 3 months ago

Has this issue been resolved yet? Is there a plan to resolve this or is it intentional behaviour to silently fail and yield no clues as to why? lol.
My own cludge is to use a conditional include statement and then do the pack manually as follows:

<ItemGroup Condition="'$(IncludeSdkFunctions)' != 'false'">
    <PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.2.0" />
</ItemGroup>

Nuget Package Manager console >dotnet pack -c Release -p:IncludeSdkFunctions=false