Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Npm and Python bug fixes #224

Merged
merged 14 commits into from
Jan 10, 2025
12 changes: 6 additions & 6 deletions src/AritfactoryUploader.UTest/ArtifactoryUploaderTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public async Task UploadPackageToRepo_InputEmptyCreds_ReturnsPackgeNotFound()
JfrogApi = "https://abc.jfrog.io/artifactory",
SrcRepoName = "org1-pythonhosted-pypi-remote-cache",
SrcRepoPathWithFullName = "org1-pythonhosted-pypi-remote-cache/6c/dd/a834df6482147d48e225a49515aabc28974ad5a4ca3215c18a882565b028/html5lib-1.1-py2.py3-none-any.whl",
PypiCompName = "html5lib-1.1-py2.py3-none-any.whl",
PypiOrNpmCompName = "html5lib-1.1-py2.py3-none-any.whl",
DestRepoName = "pypi-test",
ApiKey = "",
Email = "",
Expand Down Expand Up @@ -111,7 +111,7 @@ public async Task UploadPackageToRepo_WhenPackageInfoIsNull_ReturnsNotFoundRespo
var timeout = 10000;
var displayPackagesInfo = new DisplayPackagesInfo();
var jFrogServiceMock = new Mock<IJFrogService>();
jFrogServiceMock.Setup(x => x.GetPackageInfo(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()))
jFrogServiceMock.Setup(x => x.GetPackageInfo(component))
.ReturnsAsync((AqlResult)null);
ArtfactoryUploader.jFrogService = jFrogServiceMock.Object;
// Act
Expand Down Expand Up @@ -140,7 +140,7 @@ public async Task UploadPackageToRepo_WhenPackageTypeIsClearedThirdPartyOrDevelo
var displayPackagesInfo = new DisplayPackagesInfo();
var jFrogServiceMock = new Mock<IJFrogService>();
var jfrogApicommunicationMock = new Mock<IJFrogApiCommunication>();
jFrogServiceMock.Setup(x => x.GetPackageInfo(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()))
jFrogServiceMock.Setup(x => x.GetPackageInfo(component))
.ReturnsAsync(new AqlResult());
jfrogApicommunicationMock.Setup(x => x.CopyFromRemoteRepo(It.IsAny<ComponentsToArtifactory>()))
.ReturnsAsync(new HttpResponseMessage(HttpStatusCode.OK));
Expand Down Expand Up @@ -171,7 +171,7 @@ public async Task UploadPackageToRepo_WhenPackageTypeIsInternal_CallsMoveFromRep
var displayPackagesInfo = new DisplayPackagesInfo();
var jFrogServiceMock = new Mock<IJFrogService>();
var jfrogApicommunicationMock = new Mock<IJFrogApiCommunication>();
jFrogServiceMock.Setup(x => x.GetPackageInfo(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()))
jFrogServiceMock.Setup(x => x.GetPackageInfo(component))
.ReturnsAsync(new AqlResult());
jfrogApicommunicationMock.Setup(x => x.MoveFromRepo(It.IsAny<ComponentsToArtifactory>()))
.ReturnsAsync(new HttpResponseMessage(HttpStatusCode.OK));
Expand Down Expand Up @@ -227,7 +227,7 @@ public async Task UploadPackageToRepo_WhenHttpRequestExceptionOccurs_ReturnsErro
var displayPackagesInfo = new DisplayPackagesInfo();
var jFrogServiceMock = new Mock<IJFrogService>();
var jfrogApicommunicationMock = new Mock<IJFrogApiCommunication>();
jFrogServiceMock.Setup(x => x.GetPackageInfo(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()))
jFrogServiceMock.Setup(x => x.GetPackageInfo(component))
.ThrowsAsync(new HttpRequestException());
ArtfactoryUploader.jFrogService = jFrogServiceMock.Object;
ArtfactoryUploader.JFrogApiCommInstance = jfrogApicommunicationMock.Object;
Expand Down Expand Up @@ -257,7 +257,7 @@ public async Task UploadPackageToRepo_WhenInvalidOperationExceptionOccurs_Return
var displayPackagesInfo = new DisplayPackagesInfo();
var jFrogServiceMock = new Mock<IJFrogService>();
var jfrogApicommunicationMock = new Mock<IJFrogApiCommunication>();
jFrogServiceMock.Setup(x => x.GetPackageInfo(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()))
jFrogServiceMock.Setup(x => x.GetPackageInfo(component))
.ThrowsAsync(new InvalidOperationException());
ArtfactoryUploader.jFrogService = jFrogServiceMock.Object;
ArtfactoryUploader.JFrogApiCommInstance = jfrogApicommunicationMock.Object;
Expand Down
81 changes: 71 additions & 10 deletions src/AritfactoryUploader.UTest/PackageUploadHelperTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -406,20 +406,31 @@ public void GetUploadPackageDetails_CoversAllScenarios()
public async Task GetSrcRepoDetailsForPyPiOrConanPackages_WhenPypiRepoExists_ReturnsArtifactoryRepoName()
{
// Arrange
Property prop1 = new Property
Property repoNameProperty = new Property
{
Name = Dataconstant.Cdx_ArtifactoryRepoName,
Value = "Reponame"
};
List<Property> properties = new List<Property>() { prop1 };
List<Property> properties = new List<Property>() { repoNameProperty };
var item = new Component
{
Purl = "pypi://example-package",
Properties = properties,
Name = "pypi component",
Version = "1.0.0"
};
AqlProperty pypiNameProperty = new AqlProperty
{
Key = "pypi.normalized.name",
Value = "pypi component"
};

AqlProperty pypiVersionProperty = new AqlProperty
{
Key = "pypi.version",
Value = "1.0.0"
};
List<AqlProperty> propertys = new List<AqlProperty> { pypiNameProperty, pypiVersionProperty };
//GetInternalComponentDataByRepo
var aqlResultList = new List<AqlResult>
{
Expand All @@ -428,22 +439,24 @@ public async Task GetSrcRepoDetailsForPyPiOrConanPackages_WhenPypiRepoExists_Ret
Repo = "pypi-repo",
Path = "path/to/package",
Name = "pypi component-1.0.0",
Properties=propertys,
}
};
var jFrogServiceMock = new Mock<IJFrogService>();
jFrogServiceMock.Setup(x => x.GetInternalComponentDataByRepo(It.IsAny<string>())).ReturnsAsync(aqlResultList);

jFrogServiceMock.Setup(x => x.GetPypiComponentDataByRepo(It.IsAny<string>())).ReturnsAsync(aqlResultList);

PackageUploadHelper.jFrogService = jFrogServiceMock.Object;

// Act
var result = await PackageUploadHelper.GetSrcRepoDetailsForPyPiOrConanPackages(item);
var result = await PackageUploadHelper.GetSrcRepoDetailsForComponent(item);

// Assert
Assert.IsNotNull(result);
Assert.AreEqual("pypi-repo", result.Repo);
Assert.AreEqual("path/to/package", result.Path);
}

public async Task GetSrcRepoDetailsForPyPiOrConanPackages_WhenConanRepoExists_ReturnsArtifactoryRepoName()
public async static Task GetSrcRepoDetailsForPyPiOrConanPackages_WhenConanRepoExists_ReturnsArtifactoryRepoName()
{
// Arrange
Property prop1 = new Property
Expand Down Expand Up @@ -474,7 +487,7 @@ public async Task GetSrcRepoDetailsForPyPiOrConanPackages_WhenConanRepoExists_Re
PackageUploadHelper.jFrogService = jFrogServiceMock.Object;

// Act
var result = await PackageUploadHelper.GetSrcRepoDetailsForPyPiOrConanPackages(item);
var result = await PackageUploadHelper.GetSrcRepoDetailsForComponent(item);

// Assert
Assert.IsNotNull(result);
Expand All @@ -494,7 +507,7 @@ public async Task GetSrcRepoDetailsForPyPiOrConanPackages_WhenNoRepoExists_Retur
PackageUploadHelper.jFrogService = jFrogServiceMock.Object;

// Act
var result = await PackageUploadHelper.GetSrcRepoDetailsForPyPiOrConanPackages(item);
var result = await PackageUploadHelper.GetSrcRepoDetailsForComponent(item);

// Assert
Assert.IsNull(result);
Expand Down Expand Up @@ -744,7 +757,7 @@ public async Task GetJfrogRepoInfoForAllTypePackages_GivenDestRepoNames_ReturnsA
}

[Test]
[TestCase("NPM", "source-repo/package-name/-/package-name-1.0.0.tgz?to=/destination-repo/package-name/-/package-name-1.0.0.tgz")]
[TestCase("NPM", "?to=/destination-repo//")]
[TestCase("NUGET", "source-repo/package-name.1.0.0.nupkg?to=/destination-repo/package-name.1.0.0.nupkg")]
[TestCase("MAVEN", "source-repo/package-name/1.0.0?to=/destination-repo/package-name/1.0.0")]
[TestCase("CONAN", "source-repo/?to=/destination-repo/")]
Expand Down Expand Up @@ -798,7 +811,7 @@ public void GetCopyURL_GivenInvalidComponentType_ReturnsEmptyString()


[Test]
[TestCase("NPM", "source-repo/package-name/-/package-name-1.0.0.tgz?to=/destination-repo/package-name/-/package-name-1.0.0.tgz")]
[TestCase("NPM", "?to=/destination-repo//")]
[TestCase("NUGET", "source-repo/package-name.1.0.0.nupkg?to=/destination-repo/package-name.1.0.0.nupkg")]
[TestCase("MAVEN", "source-repo/package-name/1.0.0?to=/destination-repo/package-name/1.0.0")]
[TestCase("CONAN", "source-repo/?to=/destination-repo/")]
Expand Down Expand Up @@ -849,5 +862,53 @@ public void GetMoveURL_GivenInvalidComponentType_ReturnsEmptyString()
// Assert
Assert.AreEqual(string.Empty, result);
}

[Test]
public async Task GetSrcRepoDetailsForPyPiOrConanPackages_WhenNpmRepoExists_ReturnsArtifactoryRepoName()
{
// Arrange
var repoNameProperty = new Property
{
Name = Dataconstant.Cdx_ArtifactoryRepoName,
Value = "npm-repo"
};
var properties = new List<Property> { repoNameProperty };
var item = new Component
{
Purl = "pkg:npm/example-package",
Properties = properties,
Name = "example-package",
Version = "1.0.0"
};
var aqlResultList = new List<AqlResult>
{
new AqlResult
{
Repo = "npm-repo",
Path = "path/to/package",
Name = "example-package-1.0.0",
Properties = new List<AqlProperty>
{
new AqlProperty { Key = "npm.name", Value = "example-package" },
new AqlProperty { Key = "npm.version", Value = "1.0.0" }
}
}
};

var jFrogServiceMock = new Mock<IJFrogService>();

jFrogServiceMock.Setup(x => x.GetNpmComponentDataByRepo(It.IsAny<string>())).ReturnsAsync(aqlResultList);

PackageUploadHelper.jFrogService = jFrogServiceMock.Object;


// Act
var result = await PackageUploadHelper.GetSrcRepoDetailsForComponent(item);

// Assert
Assert.IsNotNull(result);
Assert.AreEqual("npm-repo", result.Repo);
Assert.AreEqual("path/to/package", result.Path);
}
}
}
30 changes: 7 additions & 23 deletions src/ArtifactoryUploader/ArtifactoryUploader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,11 @@ public static void SetConfigurationValues()

private static async Task<AqlResult> GetPackageInfoWithRetry(IJFrogService jFrogService, ComponentsToArtifactory component)
{
async Task<AqlResult> TryGetPackageInfo(string srcRepo, string packageName, string path)
=> await jFrogService.GetPackageInfo(srcRepo, packageName, path);
async Task<AqlResult> TryGetPackageInfo(ComponentsToArtifactory component)
=> await jFrogService.GetPackageInfo(component);

var packageInfo = await TryGetPackageInfo(component.SrcRepoName, component.JfrogPackageName, component.Path);
var packageInfo = await TryGetPackageInfo(component);


// Handle DEBIAN package name mismatch
if (component.ComponentType == "DEBIAN" && packageInfo?.Name != component.JfrogPackageName)
Expand All @@ -124,32 +125,15 @@ async Task<AqlResult> TryGetPackageInfo(string srcRepo, string packageName, stri
var lowerSrcRepo = component.SrcRepoName.ToLower();
var lowerPackageName = component.JfrogPackageName.ToLower();
var lowerPath = component.Path.ToLower();


packageInfo = await TryGetPackageInfo(lowerSrcRepo, lowerPackageName, lowerPath);
packageInfo = await TryGetPackageInfo(component);

if (packageInfo != null)
{
component.CopyPackageApiUrl = component.CopyPackageApiUrl.ToLower();
}
}

// Retry with wildcard path if still not found
// ToDo - A better way would need to be thought of in the future.
if (packageInfo == null)
{
packageInfo = await TryGetPackageInfo(component.SrcRepoName, component.JfrogPackageName, $"{component.Path}*");

if (packageInfo != null)
{
// Build URLs
string BuildUrl(string apiConstant) =>
$"{component.JfrogApi}{apiConstant}{component.SrcRepoName}/{packageInfo.Path}/{packageInfo.Name}" +
$"?to=/{component.DestRepoName}/{packageInfo.Path}/{packageInfo.Name}";

component.CopyPackageApiUrl = component.DryRun ? $"{BuildUrl(ApiConstant.CopyPackageApi)}&dry=1" : BuildUrl(ApiConstant.CopyPackageApi);
component.MovePackageApiUrl = component.DryRun ? $"{BuildUrl(ApiConstant.MovePackageApi)}&dry=1" : BuildUrl(ApiConstant.MovePackageApi);
}
}
}

return packageInfo;
}
Expand Down
Loading
Loading