Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions ReleaseNotes.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Release Notes

## 6.5.0
* Added README support. Flatcontainer will now place the README alongside the icon and nuspec files. Visual Studio package search will display README files the same as it does for nuget.org.

## 6.4.0
* Added disablePayloadSigning option for S3 feeds [PR](https://github.com/emgarten/Sleet/pull/211)

Expand Down
11 changes: 4 additions & 7 deletions build.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/env bash
set -e

# No options are needed to run a basic build and unit tests
# To run functional tests against azure and or aws, use the following options:
Expand Down Expand Up @@ -26,18 +27,14 @@ while [ : ]; do
export AWS_DEFAULT_REGION=$2
shift 2
;;
--) shift;
break
--) shift;
break
;;
esac
done

RESULTCODE=0
pushd $(pwd)

# Download dotnet cli and run tests
. build/common/common.sh
run_standard_tests

popd
exit $RESULTCODE
run_standard_tests
2 changes: 1 addition & 1 deletion build/config.props
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<AzureStorageBlobsVersion>12.20.0</AzureStorageBlobsVersion>
<JsonVersion>13.0.3</JsonVersion>
<CommandLineUtilsVersion>2.0.0</CommandLineUtilsVersion>
<NuGetTestHelpersVersion>2.1.36</NuGetTestHelpersVersion>
<NuGetTestHelpersVersion>2.1.39</NuGetTestHelpersVersion>
<PortablePdbVersion>1.5.0</PortablePdbVersion>
<AWSSDKVersion>3.7.310.4</AWSSDKVersion>
<AWSSDKTokenVersion>3.7.300.117</AWSSDKTokenVersion>
Expand Down
8 changes: 7 additions & 1 deletion src/SleetLib/Commands/InitCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ public static async Task<bool> InitAsync(LocalSettings settings, ISleetFileSyste
AddServiceIndexEntry(source.BaseURI, "registration/", "RegistrationsBaseUrl/3.4.0", "Package registrations used for search and packages.config.", serviceIndexJson);
AddServiceIndexEntry(source.BaseURI, "", "ReportAbuseUriTemplate/3.0.0", "Report abuse template.", serviceIndexJson);
AddServiceIndexEntry(source.BaseURI, "flatcontainer/", "PackageBaseAddress/3.0.0", "Packages used by project.json", serviceIndexJson);
AddServiceIndexEntry(source.BaseURI, "flatcontainer/{lower_id}/{lower_version}/readme", "ReadmeUriTemplate/6.13.0", "URI template used by NuGet Client to construct a URL for downloading a package's README.", serviceIndexJson);

// Add symbols feed if enabled
if (feedSettings.SymbolsEnabled)
Expand Down Expand Up @@ -151,10 +152,15 @@ private static void AddServiceIndexEntry(Uri baseUri, string relativeFilePath, s
private static JObject GetServiceIndexEntry(Uri baseUri, string relativeFilePath, string type, string comment)
{
var id = UriUtility.GetPath(baseUri, relativeFilePath);
var url = id.AbsoluteUri;

// Remove encoding for templates
url = url.Replace("%7Blower_id%7D", "{lower_id}");
url = url.Replace("%7Blower_version%7D", "{lower_version}");

var json = new JObject
{
["@id"] = id.AbsoluteUri,
["@id"] = url,
["@type"] = type,
["comment"] = comment
};
Expand Down
4 changes: 4 additions & 0 deletions src/SleetLib/FileSystem/AmazonS3File.cs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,10 @@ protected override async Task CopyToSource(ILogger log, CancellationToken token)
{
contentType = "image/png";
}
else if (absoluteUri.AbsoluteUri.EndsWith("/readme"))
{
contentType = "text/markdown";
}
else
{
log.LogWarning($"Unknown file type: {absoluteUri}");
Expand Down
4 changes: 4 additions & 0 deletions src/SleetLib/FileSystem/AzureFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@ protected override async Task CopyToSource(ILogger log, CancellationToken token)
{
blobHeaders.ContentType = "image/png";
}
else if (_blob.Uri.AbsoluteUri.EndsWith("/readme"))
{
blobHeaders.ContentType = "text/markdown";
}
else
{
log.LogWarning($"Unknown file type: {_blob.Uri.AbsoluteUri}");
Expand Down
56 changes: 46 additions & 10 deletions src/SleetLib/Services/FlatContainer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ private void DeleteNupkg(PackageIdentity package)
// Icon
var iconFile = _context.Source.Get(GetIconPath(package));
iconFile.Delete(_context.Log, _context.Token);

// Readme
var readmeFile = _context.Source.Get(GetReadmePath(package));
readmeFile.Delete(_context.Log, _context.Token);
}

public Uri GetNupkgPath(PackageIdentity package)
Expand Down Expand Up @@ -92,6 +96,19 @@ public static Uri GetIconPath(SleetContext context, PackageIdentity package)
return context.Source.GetPath($"/flatcontainer/{id}/{version}/icon".ToLowerInvariant());
}

public Uri GetReadmePath(PackageIdentity package)
{
return GetReadmePath(_context, package);
}

public static Uri GetReadmePath(SleetContext context, PackageIdentity package)
{
var id = package.Id;
var version = package.Version.ToIdentityString();

return context.Source.GetPath($"/flatcontainer/{id}/{version}/readme".ToLowerInvariant());
}

public Uri GetIndexUri(string id)
{
return _context.Source.GetPath($"/flatcontainer/{id}/index.json".ToLowerInvariant());
Expand Down Expand Up @@ -181,7 +198,8 @@ private Task AddPackageAsync(PackageInput packageInput)
{
AddNuspecAsync(packageInput),
AddNupkgAsync(packageInput),
AddIconAsync(packageInput)
AddIconAsync(packageInput),
AddReadmeAsync(packageInput)
});
}

Expand All @@ -206,22 +224,40 @@ private async Task AddNuspecAsync(PackageInput packageInput)
}
}

private async Task AddIconAsync(PackageInput packageInput)
private Task AddIconAsync(PackageInput packageInput)
{
// Find icon path in package from nuspec
var iconPath = packageInput.Nuspec.GetIcon();
var path = packageInput.Nuspec.GetIcon();
var feedPath = GetIconPath(packageInput.Identity);

return AddFileAsync(packageInput, path, feedPath);
}

private Task AddReadmeAsync(PackageInput packageInput)
{
// Find readme path in package from nuspec
var path = packageInput.Nuspec.GetReadme();
var feedPath = GetReadmePath(packageInput.Identity);

return AddFileAsync(packageInput, path, feedPath);
}

if (!string.IsNullOrWhiteSpace(iconPath))
private async Task AddFileAsync(PackageInput packageInput, string nupkgPath, Uri feedPath)
{
if (!string.IsNullOrWhiteSpace(nupkgPath))
{
iconPath = PathUtility.StripLeadingDirectorySeparators(iconPath).Trim();
nupkgPath = PathUtility.StripLeadingDirectorySeparators(nupkgPath).Trim();

using (var zip = packageInput.CreateZip())
if (!string.IsNullOrWhiteSpace(nupkgPath))
{
var entry = zip.GetEntry(iconPath);
if (entry != null)
using (var zip = packageInput.CreateZip())
{
var entryFile = _context.Source.Get(GetIconPath(packageInput.Identity));
await entryFile.Write(entry.Open(), _context.Log, _context.Token);
var entry = zip.GetEntry(nupkgPath);
if (entry != null)
{
var entryFile = _context.Source.Get(feedPath);
await entryFile.Write(entry.Open(), _context.Log, _context.Token);
}
}
}
}
Expand Down
31 changes: 30 additions & 1 deletion test/Sleet.AmazonS3.Tests/BasicTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,36 @@ public async Task GivenAStorageAccountVerifyPushAndRemoveSucceed()
{
await testContext.InitAsync();

var testPackage = new TestNupkg("packageA", "1.0.0");
var testPackage = new TestNupkg()
{
Nuspec = new TestNuspec()
{
Id = "packageA",
Version = "1.0.0",
Authors = "author",
Description = "desc",
IconUrl = "http://www.tempuri.org",
Icon = "images/icon.png",
Readme = "README.md",
Language = "en-us",
MinClientVersion = "1.0.0",
Title = "title",
Tags = "a b d",
Summary = "summary",
LicenseUrl = "http://www.tempuri.org/lic",
ProjectUrl = "http://www.tempuri.org/proj",
ReleaseNotes = "notes",
Owners = "owners",
Copyright = "copyright",
RequireLicenseAcceptance = "true"
},
Files = new List<TestNupkgFile>()
{
new("README.md"),
new("images/icon.png")
}
};

var zipFile = testPackage.Save(packagesFolder.Root);

var result = await InitCommand.RunAsync(testContext.LocalSettings,
Expand Down
31 changes: 30 additions & 1 deletion test/Sleet.Azure.Tests/BasicTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,36 @@ public async Task GivenAStorageAccountVerifyPushAndRemoveSucceed()
{
await testContext.InitAsync();

var testPackage = new TestNupkg("packageA", "1.0.0");
var testPackage = new TestNupkg()
{
Nuspec = new TestNuspec()
{
Id = "packageA",
Version = "1.0.0",
Authors = "author",
Description = "desc",
IconUrl = "http://www.tempuri.org",
Icon = "images/icon.png",
Readme = "README.md",
Language = "en-us",
MinClientVersion = "1.0.0",
Title = "title",
Tags = "a b d",
Summary = "summary",
LicenseUrl = "http://www.tempuri.org/lic",
ProjectUrl = "http://www.tempuri.org/proj",
ReleaseNotes = "notes",
Owners = "owners",
Copyright = "copyright",
RequireLicenseAcceptance = "true"
},
Files = new List<TestNupkgFile>()
{
new("README.md"),
new("images/icon.png")
}
};

var zipFile = testPackage.Save(packagesFolder.Root);

var result = await InitCommand.RunAsync(testContext.LocalSettings,
Expand Down
71 changes: 71 additions & 0 deletions test/SleetLib.Tests/AddRemoveTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,77 @@ public async Task AddRemove_AddAndRemovePackageWithIcon()
}
}

[Fact]
public async Task AddRemove_AddAndRemovePackageWithReadme()
{
// Arrange
using (var packagesFolder = new TestFolder())
using (var target = new TestFolder())
using (var cache = new LocalCache())
{
var log = new TestLogger();
var fileSystem = new PhysicalFileSystem(cache, UriUtility.CreateUri(target.Root));
var settings = new LocalSettings();

var context = new SleetContext()
{
Token = CancellationToken.None,
LocalSettings = settings,
Log = log,
Source = fileSystem,
SourceSettings = new FeedSettings()
{
CatalogEnabled = true
}
};

var testPackage = new TestNupkg()
{
Nuspec = new TestNuspec()
{
Id = "packageA",
Version = "1.0.0",
Authors = "author",
Description = "desc",
IconUrl = "http://www.tempuri.org",
Readme = "README.md",
Language = "en-us",
MinClientVersion = "1.0.0",
Title = "title",
Tags = "a b d",
Summary = "summary",
LicenseUrl = "http://www.tempuri.org/lic",
ProjectUrl = "http://www.tempuri.org/proj",
ReleaseNotes = "notes",
Owners = "owners",
Copyright = "copyright",
RequireLicenseAcceptance = "true"
},
Files = new List<TestNupkgFile>()
{
new("README.md")
}
};

var zipFile = testPackage.Save(packagesFolder.Root);
using (var zip = new ZipArchive(File.OpenRead(zipFile.FullName), ZipArchiveMode.Read, false))
{
var input = PackageInput.Create(zipFile.FullName);

await InitCommand.InitAsync(context);
await PushCommand.RunAsync(context.LocalSettings, context.Source, new List<string>() { zipFile.FullName }, false, false, context.Log);

var file = fileSystem.Get(fileSystem.GetPath("flatcontainer/packagea/1.0.0/readme"));
Assert.True(await file.Exists(context.Log, context.Token));

await DeleteCommand.RunAsync(context.LocalSettings, context.Source, "packageA", "1.0.0", string.Empty, false, context.Log);

file = fileSystem.Get(fileSystem.GetPath("flatcontainer/packagea/1.0.0/readme"));
Assert.False(await file.Exists(context.Log, context.Token));
}
}
}

// Verify DeletePackagesAsync method
[Fact]
public async Task AddRemove_AddAndDeletePackagesAsync()
Expand Down
1 change: 1 addition & 0 deletions test/SleetLib.Tests/InitCommandTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ public async Task GivenInitVerifyBasicOutputs()
rootJson.ToString().Should().Contain("catalog/index.json");
rootJson.ToString().Should().Contain("Catalog/3.0.0");
rootJson.ToString().Should().Contain("symbols/packages/index.json");
rootJson.ToString().Should().Contain("ReadmeUriTemplate/6.13.0");
}
}

Expand Down