Skip to content
This repository has been archived by the owner on Apr 20, 2023. It is now read-only.

Commit

Permalink
Use Rest Api to upload to the feed
Browse files Browse the repository at this point in the history
Add pulling logic to make sure it is uploaded to the feed.

Add retry logic for the whole upload process

Remove the old upload script
  • Loading branch information
William Li committed Aug 30, 2017
1 parent 8de61cd commit 5baf66d
Show file tree
Hide file tree
Showing 19 changed files with 647 additions and 214 deletions.
27 changes: 27 additions & 0 deletions Microsoft.DotNet.Cli.sln
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "tool_fsc", "src\tool_fsharp
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.MSBuildSdkResolver", "src\Microsoft.DotNet.MSBuildSdkResolver\Microsoft.DotNet.MSBuildSdkResolver.csproj", "{FCDFAF40-CC16-4D49-96C0-E49F195E7142}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dotnet-cli-build.Tests", "build_projects\dotnet-cli-build.Tests\dotnet-cli-build.Tests.csproj", "{84BB2DD5-B2D8-4C85-AAF9-29D2A74FBF94}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -1563,6 +1565,30 @@ Global
{FCDFAF40-CC16-4D49-96C0-E49F195E7142}.RelWithDebInfo|x64.Build.0 = Release|Any CPU
{FCDFAF40-CC16-4D49-96C0-E49F195E7142}.RelWithDebInfo|x86.ActiveCfg = Release|Any CPU
{FCDFAF40-CC16-4D49-96C0-E49F195E7142}.RelWithDebInfo|x86.Build.0 = Release|Any CPU
{84BB2DD5-B2D8-4C85-AAF9-29D2A74FBF94}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{84BB2DD5-B2D8-4C85-AAF9-29D2A74FBF94}.Debug|Any CPU.Build.0 = Debug|Any CPU
{84BB2DD5-B2D8-4C85-AAF9-29D2A74FBF94}.Debug|x64.ActiveCfg = Debug|Any CPU
{84BB2DD5-B2D8-4C85-AAF9-29D2A74FBF94}.Debug|x64.Build.0 = Debug|Any CPU
{84BB2DD5-B2D8-4C85-AAF9-29D2A74FBF94}.Debug|x86.ActiveCfg = Debug|Any CPU
{84BB2DD5-B2D8-4C85-AAF9-29D2A74FBF94}.Debug|x86.Build.0 = Debug|Any CPU
{84BB2DD5-B2D8-4C85-AAF9-29D2A74FBF94}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU
{84BB2DD5-B2D8-4C85-AAF9-29D2A74FBF94}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU
{84BB2DD5-B2D8-4C85-AAF9-29D2A74FBF94}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
{84BB2DD5-B2D8-4C85-AAF9-29D2A74FBF94}.MinSizeRel|x64.Build.0 = Debug|Any CPU
{84BB2DD5-B2D8-4C85-AAF9-29D2A74FBF94}.MinSizeRel|x86.ActiveCfg = Debug|Any CPU
{84BB2DD5-B2D8-4C85-AAF9-29D2A74FBF94}.MinSizeRel|x86.Build.0 = Debug|Any CPU
{84BB2DD5-B2D8-4C85-AAF9-29D2A74FBF94}.Release|Any CPU.ActiveCfg = Release|Any CPU
{84BB2DD5-B2D8-4C85-AAF9-29D2A74FBF94}.Release|Any CPU.Build.0 = Release|Any CPU
{84BB2DD5-B2D8-4C85-AAF9-29D2A74FBF94}.Release|x64.ActiveCfg = Release|Any CPU
{84BB2DD5-B2D8-4C85-AAF9-29D2A74FBF94}.Release|x64.Build.0 = Release|Any CPU
{84BB2DD5-B2D8-4C85-AAF9-29D2A74FBF94}.Release|x86.ActiveCfg = Release|Any CPU
{84BB2DD5-B2D8-4C85-AAF9-29D2A74FBF94}.Release|x86.Build.0 = Release|Any CPU
{84BB2DD5-B2D8-4C85-AAF9-29D2A74FBF94}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU
{84BB2DD5-B2D8-4C85-AAF9-29D2A74FBF94}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU
{84BB2DD5-B2D8-4C85-AAF9-29D2A74FBF94}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU
{84BB2DD5-B2D8-4C85-AAF9-29D2A74FBF94}.RelWithDebInfo|x64.Build.0 = Release|Any CPU
{84BB2DD5-B2D8-4C85-AAF9-29D2A74FBF94}.RelWithDebInfo|x86.ActiveCfg = Release|Any CPU
{84BB2DD5-B2D8-4C85-AAF9-29D2A74FBF94}.RelWithDebInfo|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -1633,6 +1659,7 @@ Global
{08A40B6A-F695-4EA9-AC8D-CF88FADEA796} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7}
{602976C5-2477-4B4C-AD9A-1EAFB250529A} = {ED2FE3E2-F7E7-4389-8231-B65123F2076F}
{FCDFAF40-CC16-4D49-96C0-E49F195E7142} = {ED2FE3E2-F7E7-4389-8231-B65123F2076F}
{84BB2DD5-B2D8-4C85-AAF9-29D2A74FBF94} = {88278B81-7649-45DC-8A6A-D3A645C5AFC3}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {B526D2CE-EE2D-4AD4-93EF-1867D90FF1F5}
Expand Down
1 change: 1 addition & 0 deletions build/Microsoft.DotNet.Cli.tasks
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
<UsingTask TaskName="TarGzFileExtractToDirectory" AssemblyFile="$(CLIBuildDll)" />
<UsingTask TaskName="UpdateVersionsRepo" AssemblyFile="$(CLIBuildDll)"/>
<UsingTask TaskName="UploadToAzure" AssemblyFile="$(CLIBuildDll)"/>
<UsingTask TaskName="UploadToLinuxPackageRepository" AssemblyFile="$(CLIBuildDll)"/>
<UsingTask TaskName="ZipFileCreateFromDirectory" AssemblyFile="$(CLIBuildDll)"/>
<UsingTask TaskName="ZipFileExtractToDirectory" AssemblyFile="$(CLIBuildDll)"/>
</Project>
2 changes: 2 additions & 0 deletions build/Test.targets
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@
<Target Name="TestsForBuildItself">
<DotNetMSBuild Arguments="/v:diag $(RepoRoot)/test/MsBuildScript.Tests/runtests.target"
ToolPath="$(Stage0Directory)" />
<DotNetTest ProjectPath="$(RepoRoot)/build_projects/dotnet-cli-build.Tests/dotnet-cli-build.Tests.csproj"
ToolPath="$(Stage0Directory)" />
</Target>

<Target Name="EnsureStageSeparation">
Expand Down
35 changes: 15 additions & 20 deletions build/publish/PublishDebian.targets
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,23 @@

<PropertyGroup>
<SdkDebianUploadUrl>$(DotnetBlobRootUrl)/$(Product)/$(FullNugetVersion)/$(DistroSpecificArtifactNameWithVersionCombinedHostHostFxrFrameworkSdk)-$(Architecture)$(InstallerExtension)</SdkDebianUploadUrl>
<DebianUploadJsonFile>$(SdkDebianIntermediateDirectory)/package_upload.json</DebianUploadJsonFile>
<DebianRevisionNumber>1</DebianRevisionNumber>

<DebianUploadJsonContent>
{
"name":"$(SdkDebianPackageName)",
"version":"$(NugetVersion)-$(DebianRevisionNumber)",
"repositoryId":"$(REPO_ID)",
"sourceUrl": "$(SdkDebianUploadUrl)"
}
</DebianUploadJsonContent>
</PropertyGroup>

<Target Name="PublishDebFilesToDebianRepo" Condition=" '$(IsDebianBaseDistro)' == 'True' AND '$(SkipPublishToDebianRepo)' != 'true' AND '$(IslinuxPortable)' != 'true' ">
<Error Condition="'$(REPO_ID)' == ''" Text="REPO_ID must be set as an environment variable for debian publishing." />
<Error Condition="'$(REPO_USER)' == ''" Text="REPO_USER must be set as an environment variable for debian publishing." />
<Error Condition="'$(REPO_PASS)' == ''" Text="REPO_PASS must be set as an environment variable for debian publishing." />
<Error Condition="'$(REPO_SERVER)' == ''" Text="REPO_SERVER must be set as an environment variable for debian publishing." />

<Delete Files="$(DebianUploadJsonFile)" />
<WriteLinesToFile File="$(DebianUploadJsonFile)" Lines="$(DebianUploadJsonContent)" />
<Target Name="PublishDebFilesToDebianRepo"
DependsOnTargets="SetupDebProps;"
Condition=" '$(IsDebianBaseDistro)' == 'True' AND '$(SkipPublishToDebianRepo)' != 'true' AND '$(IslinuxPortable)' != 'true' " >
<Error Condition="'$(REPO_ID)' == ''" Text="REPO_ID must be set as a MsBuild Property variable for debian publishing." />
<Error Condition="'$(REPO_USER)' == ''" Text="REPO_USER must be set as a MsBuild Property variable for debian publishing." />
<Error Condition="'$(REPO_PASS)' == ''" Text="REPO_PASS must be set as a MsBuild Property variable for debian publishing." />
<Error Condition="'$(REPO_SERVER)' == ''" Text="REPO_SERVER must be set as a MsBuild Property variable for debian publishing." />

<Exec Command="REPO_PASS=$(REPO_PASS) sh -c '$(RepoRoot)/scripts/publish/repoapi_client.sh -addpkg $(DebianUploadJsonFile)'" />
<UploadToLinuxPackageRepository
Username="$(REPO_USER)"
Password='$(REPO_PASS)'
Server='$(REPO_SERVER)'
RepositoryId='$(REPO_ID)'
PathOfPackageToUpload='$(SdkInstallerFile)'
PackageNameInLinuxPackageRepository='$(SdkDebianPackageName)'
PackageVersionInLinuxPackageRepository='$(NugetVersion)' />
</Target>
</Project>
92 changes: 92 additions & 0 deletions build_projects/dotnet-cli-build.Tests/GivenActionAndRetryTimes.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using FluentAssertions;
using Microsoft.DotNet.Cli.Build.UploadToLinuxPackageRepository;
using Xunit;

namespace dotnet_cli_build.Tests
{
public class GivenActionAndRetryTimes
{
public static IEnumerable<Task> NoWaitTimer()
{
while (true)
{
yield return Task.CompletedTask;
}
}

[Fact]
public void ExponentialRetryShouldProvideIntervalSequence()
{
ExponentialRetry.Intervals.First().Should().Be(TimeSpan.FromSeconds(5));
ExponentialRetry.Intervals.Skip(1).First().Should().Be(TimeSpan.FromSeconds(10));
ExponentialRetry.Intervals.Skip(2).First().Should().Be(TimeSpan.FromSeconds(20));
ExponentialRetry.Intervals.Skip(3).First().Should().Be(TimeSpan.FromSeconds(40));
ExponentialRetry.Intervals.Skip(4).First().Should().Be(TimeSpan.FromSeconds(80));
}

[Fact]
public void ExponentialShouldNotRetryAfterFirstSucceess()
{
var fakeAction = new FakeAction(0);
ExponentialRetry.ExecuteWithRetry(
fakeAction.Run,
s => s == "success",
10,
NoWaitTimer).Wait();
fakeAction.Count.Should().Be(0);
}

[Fact]
public void ExponentialShouldRetryUntilSuccess()
{
var fakeAction = new FakeAction(5);
ExponentialRetry.ExecuteWithRetry(
fakeAction.Run,
s => s == "success",
10,
NoWaitTimer).Wait();
fakeAction.Count.Should().Be(5);
}

[Fact]
public void ExponentialShouldThrowAfterMaximumAmountReached()
{
var fakeAction = new FakeAction(10);
Action a = () => ExponentialRetry.ExecuteWithRetry(
fakeAction.Run,
s => s == "success",
5,
NoWaitTimer,
"testing retry").Wait();
a.ShouldThrow<RetryFailedException>()
.WithMessage("Retry failed for testing retry after 5 times with result: fail");
}
}

public class FakeAction
{
private readonly int _successAfter;

public FakeAction(int successAfter)
{
_successAfter = successAfter;
}

public int Count { get; private set; }

public Task<string> Run()
{
if (_successAfter == Count)
{
return Task.FromResult("success");
}

Count++;
return Task.FromResult("fail");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />

<PropertyGroup>
<TargetFramework>$(CliTargetFramework)</TargetFramework>
<VersionPrefix>1.0.0</VersionPrefix>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81</AssetTargetFallback>
<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(CLI_TestPlatform_Version)" />
<PackageReference Include="xunit" Version="2.2.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
<PackageReference Include="FluentAssertions" Version="4.18.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\dotnet-cli-build\dotnet-cli-build.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using NuGet.Protocol;

namespace Microsoft.DotNet.Cli.Build.UploadToLinuxPackageRepository
{
internal class AddPackageStrategy : IAzurelinuxRepositoryServiceHttpStrategy
{
private readonly IdInRepositoryService _idInRepositoryService;
private readonly string _packageName;
private readonly string _packageVersion;
private readonly string _repositoryId;

public AddPackageStrategy(
IdInRepositoryService idInRepositoryService,
string packageName,
string packageVersion,
string repositoryId)
{
_idInRepositoryService = idInRepositoryService
?? throw new ArgumentNullException(nameof(idInRepositoryService));
_packageName = packageName;
_packageVersion = packageVersion;
_repositoryId = repositoryId;
}

public async Task<string> Execute(HttpClient client, Uri baseAddress)
{
var debianUploadJsonContent = new Dictionary<string, string>
{
["name"] = _packageName,
["version"] = AppendDebianRevisionNumber(_packageVersion),
["fileId"] = _idInRepositoryService.Id,
["repositoryId"] = _repositoryId
}.ToJson();
var content = new StringContent(debianUploadJsonContent,
Encoding.UTF8,
"application/json");

using (var response = await client.PostAsync(new Uri(baseAddress, "/v1/packages"), content))
{
if (!response.IsSuccessStatusCode)
throw new FailedToAddPackageToPackageRepositoryException(
$"request:{debianUploadJsonContent} response:{response.ToJson()}");
return response.Headers.GetValues("Location").Single();
}
}

private static string AppendDebianRevisionNumber(string packageVersion)
{
return packageVersion + "-1";
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Microsoft.DotNet.Cli.Build.UploadToLinuxPackageRepository
{
public static class ExponentialRetry
{
public static IEnumerable<TimeSpan> Intervals
{
get
{
var seconds = 5;
while (true)
{
yield return TimeSpan.FromSeconds(seconds);
seconds *= 2;
}
}
}

public static async Task ExecuteWithRetry(Func<Task<string>> action,
Func<string, bool> isSuccess,
int maxRetryCount,
Func<IEnumerable<Task>> timer,
string taskDescription = "")
{
var count = 0;
foreach (var t in timer())
{
await t;
var result = await action();
if (isSuccess(result))
return;
count++;
if (count == maxRetryCount)
throw new RetryFailedException(
$"Retry failed for {taskDescription} after {count} times with result: {result}");
}
throw new Exception("Timer should not be exhausted");
}

public static IEnumerable<Task> Timer(IEnumerable<TimeSpan> interval)
{
return interval.Select(Task.Delay);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;

namespace Microsoft.DotNet.Cli.Build.UploadToLinuxPackageRepository
{
public class FailedToAddPackageToPackageRepositoryException : Exception
{
public FailedToAddPackageToPackageRepositoryException(string message) : base(message)
{
}

public FailedToAddPackageToPackageRepositoryException()
{
}

public FailedToAddPackageToPackageRepositoryException(string message, Exception innerException) : base(message,
innerException)
{
}
}
}
Loading

0 comments on commit 5baf66d

Please sign in to comment.