MyGet Blog

Package management made easier!

NAVIGATION - SEARCH

Introducing MyGet Vsix support–Visual Studio Extensions and Roslyn

Last month, we introduced a limited preview for Visual Studio extensions (Vsix) on MyGet. Today, we’re proud to announce Vsix support has been enabled for all MyGet customers! In this blog post, we’ll see how we can use MyGet to build and distribute a Roslyn analyzer and code fix, as a NuGet package and a Visual Studio extension.

The full feature set we already have for NuGet, Bower and NPM is now also available for Vsix. You're able to manage extensions, add them from upstream feeds (ATOM only), granular permissions and user management, support for community feeds... If you need a staging feed or just a private VSIX gallery, this is the easiest way to get one. Using the VSO integration? We'll pick up the VSIX artifacts from your VSO build and automatically add them to your MyGet VSIX feed. Here’s an example.

(we also open sourced the example at https://github.com/myget/sample-roslyn-with-vsix)

Developing a Roslyn analyzer and code fix

Roslyn analyzers and code fixes allow development teams and individuals to enforce certain rules within a code base. Using code fixes, it’s also possible to provide automated “fixes” for issues found in code. When writing code that utilizes DateTime, it’s often best to use DateTime.UtcNow instead of DateTime.Now. The first uses UTC timezone, while the latter uses the local time zone of the computer the code runs on, often introducing nasty time-related bugs. Let’s write an analyzer that detects usage of DateTime.Now!

You will need Visual Studio 2015 RC and the Visual Studio 2015 RC SDK installed. You’ll also need the SDK Templates VSIX package to get the Visual Studio project templates. Once you have those, we can create a new Analyzer with Code Fix.

New Roslyn analyzer

A solution with 3 projects will be created: the analyzer and code fix, unit tests and a Vsix project. Let’s start with the first: detecting DateTime.Now in code an showing a diagnostic for it. It’s actually quite easy to do: we tell Roslyn we want to analyze IdentifierName nodes and it will pass them to our code. We can then see if the identifier is “Now” and the parent node is “DateTime”. If that’s the case, return a diagnostic:

public override void Initialize(AnalysisContext context) { context.RegisterSyntaxNodeAction(AnalyzeIdentifierName, SyntaxKind.IdentifierName); } private void AnalyzeIdentifierName(SyntaxNodeAnalysisContext context) { var identifierName = context.Node as IdentifierNameSyntax; if (identifierName != null) { // Find usages of "DateTime.Now" if (identifierName.Identifier.ValueText == "Now" && ((IdentifierNameSyntax)((MemberAccessExpressionSyntax)identifierName.Parent).Expression).Identifier.ValueText == "DateTime") { // Produce a diagnostic. var diagnostic = Diagnostic.Create(Rule, identifierName.Identifier.GetLocation(), identifierName); context.ReportDiagnostic(diagnostic); } } }

If we compile our solution and add the generated NuGet package to another project, DateTime.Now code will be flagged. But let’s implement the code fix first as well. We want to provide a code fix for the syntax node we just detected. And when we invoke it, we want to replace the “Now” node with “UtcNow”. A bit of Roslyn syntax tree fiddling:

public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); var diagnostic = context.Diagnostics.First(); var diagnosticSpan = diagnostic.Location.SourceSpan; // Find "Now" var identifierNode = root.FindNode(diagnosticSpan); // Register a code action that will invoke the fix. context.RegisterCodeFix( CodeAction.Create("Replace with DateTime.UtcNow", c => ReplaceWithDateTimeUtcNow(context.Document, identifierNode, c)), diagnostic); } private async Task<Document> ReplaceWithDateTimeUtcNow(Document document, SyntaxNode identifierNode, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken); var newRoot = root.ReplaceNode(identifierNode, SyntaxFactory.IdentifierName("UtcNow")); return document.WithSyntaxRoot(newRoot); }

That’s it. We now have an analyzer and a code fix. If we try it (again, by adding the generated NuGet package to another project), we can see both in action:

MyGet Roslyn analyzer VSIX and NuGet

Now let’s distribute it to our team!

Distributing a Roslyn analyzer and code fix using MyGet

Roslyn analyzers can be distributed in two formats: as NuGet packages, so they can be enabled for individual project, and as a Visual Studio extension so that all projects we work with have the analyzer and code fix enabled. You can build on a developer machine, a CI server or using MyGet Build Services. Let’s pick the latter as it’s the easiest way to achieve our goal: compile and distribute.

Create a new feed on www.myget.org. Next, from the Build Services tab, we can add a GitHub repository as the source. We’ve open-sourced our example at https://github.com/myget/sample-roslyn-with-vsix so feel free to add it to your feed as a test. Once added, you can start a build. Just like that. MyGet will figure out it’s a Roslyn analyzer and build both the NuGet package as well as the Visual Studio extension.

MyGet automated build of visual studio extension

Sweet! You can now add the Roslyn analyzer and code fix per-project, by installing the NuGet package from the feed (https://www.myget.org/F/datetime-analyzer/api/v2). ANd when registering it in Visual Studio (https://www.myget.org/F/datetime-analyzer/vsix/) by opening the Tools | Options... menu and the Environment | Extensions and Updates pane, you can also install the full extension.

Private VSIX feed with MyGet

Give it a try! More info is available from the Visual Studio extension landing page or the documentation on using MyGet’s Vsix features.

Happy packaging!

Working with scoped npm packages and MyGet private registry

When we introduced npm support on MyGet last month, we did not yet have support for scoped packages. Today, we’re pleased to announce full support for them!

Scoped packages are packages that are "scoped" to a specific registry. E.g. all packages scoped @acmecorp may be retrieved from a MyGet npm registry feed, while other scopes and non-scoped packages flow in from the default npm registry.

Creating a scoped package

A scoped package can be created by setting the name property in package.json file correctly, for example:

{
  "name": "@acmecorp/awesomeapplication",
  "version": "1.0.0"
}

Dependencies can be scoped as well:

{
  "name": "@acmecorp/awesomeapplication",
  "version": "1.0.0",
  "dependencies": {
    "@acmecorp/awesomepackage": "1.0.0"
  }
}

More information on scoped packages is available from the npm docs.

Publishing a scoped package

Scopes can be associated with a specific registry. This allows for seamless mixing of packages from various npm registries.

Let's associate the scope @acmecorp with the https://www.myget.org/F/your-feed-name/npm/ npm registry feed. We can do this manually, by adding the following to our .npmrc file:

@acmecorp:registry=https://www.myget.org/F/your-feed-name/npm/
//www.myget.org/F/your-feed-name/npm/:_password="base64encodedpassword"
//www.myget.org/F/your-feed-name/npm/:username=someuser
//www.myget.org/F/your-feed-name/npm/:email=someuser@example.com
//www.myget.org/F/your-feed-name/npm/:always-auth=true

It's probably easier to generate these entries from the command line by running:

npm config set @acmecorp:registry=https://www.myget.org/F/your-feed-name/npm/
npm login --registry https://www.myget.org/F/your-feed-name/npm/ --scope=@acmecorp
npm config set always-auth true --registry https://www.myget.org/F/your-feed-name/npm/

From now on, we can publish and consume any package that has the @acmecorp scope. Npm will automatically direct requests to the correct registry.

Happy packaging!

P.S.: We have VSIX support coming as well. Let us know if you want to enroll in the preview.

MyGet now offers NuGet, Npm and Bower registries

pmsWith our latest MyGet release, we’ve added support for npm and bower registries. We’ve always been very focused on building a great story around NuGet and decided it was time for Npm and Bower enthusiasts to get a similar experience.

Adding npm and Bower support was high on our wish list and that of our users. Many developers are doing only front-end development and need a public or private npm registry. Others are working with DNX (the new name for ASP.NET 5 or ASP.NET vNext) and combine NuGet, npm and Bower. It feels good to be able to support them all!

To help you get started, we’ve prepared a few short tutorials that help you get started on MyGet with these package managers:

Oh and build services now also packages node modules! Just point MyGet to your GitHub repository and we’ll package your npm packages, too.

We really look forward to hearing your feedback on this!

Happy packaging!

Introducing MyGet Feed Sync

How can you keep multiple local NuGet servers synchronized? How can developers consume the same packages when each office branch has its own local NuGet server? How can two servers be synchronized when bandwidth is insufficient for a cloud-only solution?

We’re happy to introduce Feed Sync. Jointly developed by MyGet and Inedo ProGet, allows you to synchronize packages on multiple package servers with MyGet.

Note: During preview, Feed Sync is available for all MyGet plans and Inedo ProGet free users. After release, Feed Sync will be available for all paid MyGet plans and users of ProGet Enterprise 3.5 and up.

Synchronize local NuGet server with MyGet

Packages added on a linked ProGet instance will be replicated to MyGet and any other linked instance. When using MyGet Build Services to build packages from GitHub, BitBucket or Visual Studio Online, packages that are created will be replicated as well.

Read up on how to configure Feed Sync in our documentation.

Happy packaging!

IP whitelisting for MyGet Enterprise customers

Many enterprises access the Internet using one or more static IP addresses and prefer limiting access to their applications to those IP addresses. Good news: MyGet Enterprise customers can now whitelist IP addresses (or IP ranges) so only clients can only access MyGet if they are coming from the configured address. The whitelist will be applied for accessing the website, as well as for consuming hosted NuGet feeds.

IP whitelisting for MyGet Enterprise customers

Enterprise administrators can navigate to the administration dashboard, and create an IP whitelist under the Accounts tab. IP addresses can be entered on separate lines. If an entire subnet has to have access, the IP address can be suffixed with a CIDR suffix (e.g. /24) or a subnet mask (e.g. /255.255.255.0).

Happy packaging!

Could not load file or assembly… NuGet Assembly Redirects

When working in larger projects, you will sometimes encounter errors similar to this one: “Could not load file or assembly 'Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' or one of its dependencies. The system cannot find the file specified.” Or how about this one? “System.IO.FileLoadException : Could not load file or assembly 'Moq, Version=3.1.416.3, Culture=neutral, PublicKeyToken=69f491c39445e920' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)

Search all you want, most things you find on the Internet are from the pre-NuGet era and don’t really help. What now? In this post, let’s go over why this error sometimes happens. And I’ll end with a beautiful little trick that fixes this issue when you encounter it. Let’s go!

Redirecting Assembly Versions

In 90% of the cases, the errors mentioned earlier are caused by faulty assembly redirects. What are those, you ask? A long answer is on MSDN, a short answer is that assembly redirects let us trick .NET into believing that assembly A is actually assembly B. Or in other words, we can tell .NET to work with Newtonsoft.Json 6.0.0.4 whenever any other reference requires an older version of Newtonsoft.Json.

Assembly redirects are often created by NuGet, to solve versioning issues. Here’s an example which I took from an application’s Web.config:

<?xml version="1.0" encoding="utf-8"?> <configuration> <!-- ... --> <runtime> <legacyHMACWarning enabled="0" /> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" /> </dependentAssembly> </assemblyBinding> </runtime> </configuration>

When running an application with this config file, it will trick any assembly that wants to use any version < 6.0.0.0 of Newtonsoft.Json into working with the latest 6.0.0.0 version. Neat, as it solves dependency hell where two assemblies require a different version of a common assembly dependency. But… does it solve that?

NuGet and Assembly Redirects

The cool thing about NuGet is that it auto-detects whenever assembly redirects are needed, and adds them to the Web.config or App.config file of your project. However, this not always works well. Sometimes, old binding redirects are not removed. Sometimes, none are added at all. Resulting in fine errors like the ones I opened this post with. At compile time. Or worse! When running the application.

One way of solving this is manually checking all binding redirects in all configuration files you have in your project, checking assembly versions and so on. But here comes the trick: we can let NuGet do this for us!

All we have to do is this:

  1. From any .config file, remove the <assemblyBinding> element and its child elements. In other words: strip your app from assembly binding redirects.
  2. Open the Package Manager Console in Visual Studio. This can be done from the View | Other Windows | Package Manager Console menu.
  3. Type this one, magical command that solves it all: Get-Project -All | Add-BindingRedirect. I repeat: Get-Project -All | Add-BindingRedirect

NuGet Add Binding Redirect

NuGet will get all projects and for every project, add the correct assembly binding redirects again. Compile, run, and continue your day without rage. Enjoy!

PS: For the other cases where this trick does not help, check Damir Dobric’s post on troubleshooting NuGet references.

Build Services - Introducing pre- and post-build steps

With our 1.9.5 release out of the door, we’ve introduced support for pre- and post-build steps in MyGet Build Services. When using batch / PowerShell based builds for building your GitHub, BitBucket or Visual Studio Online projects and making NuGet packages for them, MyGet Build Services will scan for batch files to be executed. In addition to the default build.bat (or .cmd or .ps1), we search for pre- and post-build steps as well. These can be batch scripts or PowerShell scripts that are run before and after the actual build file.

When using MyGet Service Messages in the build, pre- and post-build steps can be used to prepare the build environment by setting the correct package version number, or creating additional environment variables for use by the build script.

More information can be found in our docs.

Happy packaging!

Web hooks released - Integrate MyGet with other services

A few weeks back, we announced the preview of MyGet web hooks. Today, we’re happy to say we’ve released web hooks for all our users. With web hooks, your feeds can communicate with external services whenever a specific action occurs on the feed. Events can be posted to your web server, e-mail, Twilio, Twitter, Visual Studio Online Team Rooms, HipChat and Slack.

Web hook types

Webhooks can be used to perform actions based on an event, for example sending out a tweet when a package is pushed or updating an issue tracker when a build succeeds. We’ve blogged some demos, for example on how to strong-name sign packages when added to a feed and how to implement custom retention policies. It’s not always required to write custom code though: we integrate with a variety of services such as Twitter, Twilio, HipChat and starting today, with Visual Studio Online Team Rooms and Slack.

Slack integration with MyGet

Only feed owners and co-owners can manage webhooks for a feed. Each webhook can be triggered for one or more event types, depending on the implementation. Webhook deliveries can be inspected, including full logs, as well as redelivered in case this is needed. Give web hooks a go!

Happy packaging!

Implementing custom package retention using webhooks

Earlier this week, we got the question if custom retention policies could be enforced on MyGet. More specific, the request was to be able to keep the latest 5 versions of a minor version (e.g. keep 1.0.6 through 1.0.2, but delete 1.0.1 and 1.0.0). We’ve introduced webhooks on MyGet to enable exactly this sort of scenarios!

Our own retention policies run whenever a package is added to a feed, so let’s see if we can implement a webhook handler that does exactly what was asked… The code for this blog post can be found in our GitHub organization.

Building the webhook handler

We’ll first need something that can run our custom logic whenever a webhook event is raised. This can be an ASP.NET MVC, Web API, NancyFx or even a PHP application. In this case, let’s go with an ASP.NET Web API controller. We want to be triggered on POST when a package added event is raised.

// POST /api/retention public async Task<HttpResponseMessage> Post([FromBody]WebHookEvent payload) { // The logic in this method will do the following: // 1) Find all packages with the same identifier as the package that was added to the originating feed // 2) Enforce the following policy: only the 5 latest (stable) packages matching the same minor version may remain on the feed. Others should be removed. string feedUrl = payload.Payload.FeedUrl; // Note: the following modifies NuGet's client so that we authenticate every request using the API key. // If credentials (e.g. username/password) are preferred, set the NuGet.HttpClient.DefaultCredentialProvider instead. PackageRepositoryFactory.Default.HttpClientFactory = uri => { var client = new NuGet.HttpClient(uri); client.SendingRequest += (sender, args) => { args.Request.Headers.Add("X-NuGet-ApiKey", ConfigurationManager.AppSettings["Retention:NuGetFeedApiKey"]); }; return client; }; // Prepare HttpClient (non-NuGet) var httpClient = new HttpClient(); httpClient.DefaultRequestHeaders.Add("X-NuGet-ApiKey", ConfigurationManager.AppSettings["Retention:NuGetFeedApiKey"]); // Fetch packages and group them (note: only doing this for stable packages, ignoring prerelease) var packageRepository = PackageRepositoryFactory.Default.CreateRepository(feedUrl); var packages = packageRepository.GetPackages().Where(p => p.Id == payload.Payload.PackageIdentifier).ToList(); foreach (var packageGroup in packages.Where(p => p.IsReleaseVersion()) .GroupBy(p => p.Version.Version.Major + "." + p.Version.Version.Minor)) { foreach (var package in packageGroup.OrderByDescending(p => p.Version).Skip(5)) { await httpClient.DeleteAsync(string.Format("{0}api/v2/package/{1}/{2}?hardDelete=true", feedUrl, package.Id, package.Version)); } } return new HttpResponseMessage(HttpStatusCode.OK) { ReasonPhrase = "Custom retention policy applied." }; }

Once we have this in place and are hosting it somewhere, we can configure the webhook on our MyGet feed.

Configuring the webhook

On our MyGet feed, we can create a new webhook. It should send application/json for the package added event to the URL where we deployed the above code.

Configure web hook

When this hook now triggers, we will be retaining just the 5 latest minor versions of a package (ignoring prereleases).

That’s it. Using nothing but webhooks, we can run our own retention policies (or other logic) when something happens on our feed (like strong-name signing packages, for example). There are a number of events that we can subscribe to!

Happy packaging!

User-defined environment variables in MyGet builds

Sometimes you may want to pass in a value to the build scripts without hard-coding it into the build script. MyGet now supports setting additional environment variables (that can be used in custom build scripts as well as plain MSBuild). From the Build Source configuration, you can add up to 15 environment variables that will be made available during build.

Edit environment variables

The open/closed eye icon next to the environment variable can be used to show/hide the environment variable value in the build log. Sometimes it is not desirable to have things like passwords or API keys shown in the build log, and by making the environment variable hidden we’ll hide it in the build log.

Shown in build log

Happy packaging!