Some time ago I posted the following question on twitter:
has anyone done a serverless @nuget gallery using azure functions and blob storage? I totally need one ;)
I was basically looking for a serverless solution that would be independent of our CI so that multiple builds from various sources we have around could push nuget packages in a consistent fashion and we could access them reliably without the burden of maintaining a nuget gallery.
I’d argue the need for a full-blown nuget.org-like website/gallery is typically unnecessary, unless you’re hosting this for end users. But for enterprises, internal dogfooding and even personal projects, all you typically need is a reliable and fast feed.
I wanted an even more streamlined experience for the serverless Azure Blob Storage-based solution, with explicit support for MSBuild. Basically I wanted to:
- Install/restore a nuget package
- Declare via MSBuild some .nupkg(s) to push
So extending his awesome tool, I created the Sleet.Azure package, which does exactly that.
All you need to provide are the following properties:
<!-- Azure storage access key for the connection --> <StorageAccessKey Condition="'$(StorageAccessKey)' == ''" /> <!-- Azure storage account to use (aka "the sub-domain" in *.blob.core.windows.net or *.azureedge.net for the CDN endpoint) --> <StorageAccount Condition="'$(StorageAccount)' == ''" /> <!-- Azure storage container name where the feed will be stored (aka "the folder") --> <StorageContainer Condition="'$(StorageContainer)' == ''" />
Then the packages you intend to push:
<ItemGroup> <Package Include="bin\*.nupkg" > </ItemGroup>
And finally just invoke
msbuild /t:push on that project.
Combined with trivially created nuget packages in VS2017, this allows you to quickly get a private Azure Storage-based feed up and running with no code and no fuss. And it’s even automatically CDN enabled!
Push will validate and automatically initialize (if empty or non-existing)
the feed on every push. This is a somewhat costly and slow-ish operation. So you can
<SleetInit>false</SleetInit> (or pass in
Init target just once before the first