NuGet/NuGetGallery — pull request #1440 by anurse (2013-08-16 18:47:03+00:00)
Title: Fix #1258 by adding friendly license name reports

(Interested in the code? Jump below thes first two sections for more info)

# Conflict resolution notes
There are three conflicts as of my last dry-run merge into dev.
* src/NuGetGallery.Core/Entities/EntitiesContext.cs - This shows as no actual conflict in my merge tool (p4merge), should be a simple merge
* src/NuGetGallery.Operations/Tasks/TaskBases.cs - Same
* src/NuGetGallery/Services/PackageService.cs - Just a conflict around the removal of ".Include(p => p.Authors)" and the addition of ".Include(p => p.LicenseReports)". Since the data was denomalized, you can remove the ".Include(p => p.LicenseReports)" or keep it, as you like :)

# Deployment notes:
- [ ] Run migrations BEFORE deploying
- [ ] Add the following config settings with values taken from our usual secret store to the WORKER CSCFG:
* Operations.LicenseReport.Service - URL to the license reports service
* Operations.LicenseReport.User - User name for the service
* Operations.LicenseReport.Password - Password for the service
- [ ] 10-15 mins after deployment, check the "wad-joblogs" container in the storage account (i.e. nugetqa) for files named UpdateLicenseReportsJob.[date].json. These contain the log output of the job. Connectivity errors are expected occasionally but the service should continue to process reports as it is able to retrieve them.

# About the code
The code is fairly straightforward. There is a new worker Task, UpdateLicenseReportsTask. It queries the service until no more data is available, then sleeps for 30mins. The data is inserted using a new SPROC (AddLicenseReport) that is created in a Gallery migration. The data is stored in two forms: A normalized structure using PackageLicenses, PackageLicenseReports and PackageLicenseReportLicenses (woo, table naming!), and a denormalized structure consisting of two new columns in Packages (LicenseNames, a comma separated list of licenses, and LicenseReportUrl). The SPROC updates BOTH the normalized and denormalized structure, but if we notice the denormalized structure getting out of date, we can rebuild it, we have the technology.

The display is also simple. Admins can always see reports, even when the feature is disabled. When the feature is enabled, Owners can always see their reports, and **by default** all users can see the report for a package. The owner can choose to opt-out of the report from the Display Package page. This change is immediate on the same instance, but must wait until the next Lucene index update to propagate to the other instance(s).

The feature is controlled by a Web.config setting: "Feature.FriendlyLicenses". There is also a small infrastructure (in src/NuGetGallery/Configuration/FeatureConfiguration.cs) for managing future feature switches. By default, the lack of the relevant web.config setting indicates that the feature is **disabled**. Once the feature is announced, we can REMOVE the feature switch in the next deployment (to avoid clutter).

# If you have comments
Please note that I am OOF starting at the end of today, so unfortunately comments will be difficult to address. Feel free to update the PR yourself as necessary :).