Skip to content

Commit 9e0987c

Browse files
authored
Merge pull request #349 from siemens/feature/PackageIdentifierForCargo
feat: Package identifier for cargo.
2 parents 8ce72a1 + 4a5d79e commit 9e0987c

File tree

47 files changed

+19615
-336
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+19615
-336
lines changed

TestFiles/IntegrationTestFiles/SpdxTestFiles/Cargo/Cargo.spdx.sbom.json

Lines changed: 11437 additions & 0 deletions
Large diffs are not rendered by default.

TestFiles/IntegrationTestFiles/SystemTest1stIterationData/Cargo/cargo.metadata.json

Lines changed: 3277 additions & 0 deletions
Large diffs are not rendered by default.

doc/UsageDoc/CA_UsageDocument.md

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959

6060

6161
# Introduction
62-
Welcome to the Continuous Clearing Tool, your automated solution for streamlining the SW360 clearing process. Designed with Project Managers and Developers in mind, this tool efficiently manages third-party components across various platforms, including NPM, NuGet, Maven, Python, Conan, Alpine, and Debian.
62+
Welcome to the Continuous Clearing Tool, your automated solution for streamlining the SW360 clearing process. Designed with Project Managers and Developers in mind, this tool efficiently manages third-party components across various platforms, including NPM, NuGet, Maven, Python, Conan, Cargo, Alpine, and Debian.
6363

6464
## Key Features
6565
- **Automated Scanning and Identification**: The tool automatically scans and identifies third-party components in your projects.
@@ -77,17 +77,17 @@ Simply integrate the Continuous Clearing Tool into your project workflow to expe
7777

7878
# Continuous Clearing Tool workflow diagram
7979
* Package Identifier
80-
* [NPM/NUGET/MAVEN/PYTHON/CONAN](../usagedocimg/packageIdentifiernpmnuget.PNG)
80+
* [NPM/NUGET/MAVEN/PYTHON/CONAN/CARGO](../usagedocimg/packageIdentifiernpmnuget.PNG)
8181
* [Debian/Alpine](../usagedocimg/packageIdentifierdebianalpine.PNG)
8282
* [BasicSBOM](../usagedocimg/PackageidentifierBasicSBOMflowdiagram.png)
8383

8484
* SW360 Package Creator
85-
* [NPM/NUGET/MAVEN/PYTHON/CONAN](../usagedocimg/packageCreatirnpmnuget.PNG)
85+
* [NPM/NUGET/MAVEN/PYTHON/CONAN/CARGO](../usagedocimg/packageCreatirnpmnuget.PNG)
8686
* [Debian](../usagedocimg/packagecreatordebian.PNG)
8787
* [Alpine](../usagedocimg/ComponentcreaterforAlpine.PNG)
8888

8989
* Artifactory Uploader
90-
* [NPM/NUGET/MAVEN/PYTHON/CONAN](../usagedocimg/artifactoryuploader.PNG)
90+
* [NPM/NUGET/MAVEN/PYTHON/CONAN?CARGO](../usagedocimg/artifactoryuploader.PNG)
9191

9292
# Prerequisite
9393
To ensure a smooth operation of the Continuous Clearing Tool, please follow these prerequisites:
@@ -196,6 +196,17 @@ Users have the flexibility to generate a basic SBOM even if connections to SW360
196196
* **Project Type :** **Conan**
197197
198198
* Input file repository should contain **conan.lock** file.
199+
200+
* **Project Type :** **Cargo**
201+
202+
* Run the command given below (i.e., To generate a metadata file for your project, run the following command in your project directory (where your Cargo.toml is located)) .
203+
204+
* For creating metadata.json file you can use the format version 1.
205+
206+
**Example**: cargo metadata --format-version 1 > cargo.metadata.json
207+
After successful execution, *.metadata.json file will be created in specified directory .
208+
209+
Resulted cargo.metadata.json file will be having the list of installed packages and the same file will be used as an input to Continuous clearing tool - Package identifier via the input directory parameter. The remaining process is same as other project types.
199210
200211
* **Project Type :** **Debian & Alpine**
201212
@@ -254,7 +265,7 @@ Description for the settings in appSettings.json file
254265
| S.No | Argument Name | Description | Mandatory | Example |
255266
| ---- | ----------------------------------------- | ------------------------------------------------------------- | --------------- | ------------------------------------------------------------------------ |
256267
| 1 | TimeOut | Timeout in seconds | No | 400 |
257-
| 2 | ProjectType | Type of the project | Yes | `Nuget`, `NPM`, `Poetry`, `Conan`, `Alpine`, `Debian`, `Maven` |
268+
| 2 | ProjectType | Type of the project | Yes | `Nuget`, `NPM`, `Poetry`, `Conan`, `Alpine`, `Debian`, `Maven`, `Cargo` |
258269
| 3 | MultipleProjectType | Whether multiple project types are supported | No | `False` |
259270
| 4 | Telemetry.Enable | Enable telemetry | No | `False` |
260271
| 5 | Telemetry.ApplicationInsightsConnectionString | Application Insights instrumentation key | No | `123-456-789-123-123` |

src/AritfactoryUploader.UTest/PackageUploadHelperTest.cs

Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ public void GetComponentListFromComparisonBOM_GivenComparisonBOM_ReturnsComponen
4949
[TestCase("DEBIAN", ".deb")]
5050
[TestCase("POETRY", ".whl")]
5151
[TestCase("CONAN", "package.tgz")]
52+
[TestCase("CARGO", ".crate")]
5253
public void GetPkgeNameExtensionBasedOnComponentType_GivenType_ReturnsPkgNameExtension(string type, string extension)
5354
{
5455
// Arrange
@@ -212,6 +213,7 @@ public void GetJfrogApiCommInstance_GivenComponentWithUnknownType_ReturnsJfrogAp
212213
[TestCase("POETRY")]
213214
[TestCase("CONAN")]
214215
[TestCase("DEBIAN")]
216+
[TestCase("CARGO")]
215217
public async Task JfrogNotFoundPackagesAsync_CoversAllScenarios(string compType)
216218
{
217219
// Arrange
@@ -224,6 +226,7 @@ public async Task JfrogNotFoundPackagesAsync_CoversAllScenarios(string compType)
224226
displayPackagesInfo.JfrogNotFoundPackagesPython = new List<ComponentsToArtifactory>();
225227
displayPackagesInfo.JfrogNotFoundPackagesConan = new List<ComponentsToArtifactory>();
226228
displayPackagesInfo.JfrogNotFoundPackagesDebian = new List<ComponentsToArtifactory>();
229+
displayPackagesInfo.JfrogNotFoundPackagesCargo = new List<ComponentsToArtifactory>();
227230

228231
// Act
229232
await PackageUploadHelper.JfrogNotFoundPackagesAsync(item, displayPackagesInfo);
@@ -259,6 +262,11 @@ public async Task JfrogNotFoundPackagesAsync_CoversAllScenarios(string compType)
259262
Assert.AreEqual(1, displayPackagesInfo.JfrogNotFoundPackagesDebian.Count);
260263
Assert.That(displayPackagesInfo.JfrogNotFoundPackagesDebian[0], Is.Not.Null);
261264
}
265+
else if (item.ComponentType == "CARGO")
266+
{
267+
Assert.AreEqual(1, displayPackagesInfo.JfrogNotFoundPackagesCargo.Count);
268+
Assert.That(displayPackagesInfo.JfrogNotFoundPackagesCargo[0], Is.Not.Null);
269+
}
262270
}
263271

264272
[Test]
@@ -268,6 +276,7 @@ public async Task JfrogNotFoundPackagesAsync_CoversAllScenarios(string compType)
268276
[TestCase("POETRY")]
269277
[TestCase("CONAN")]
270278
[TestCase("DEBIAN")]
279+
[TestCase("CARGO")]
271280
public async Task JfrogFoundPackagesAsync_CoversAllScenarios(string compType)
272281
{
273282
// Arrange
@@ -280,6 +289,7 @@ public async Task JfrogFoundPackagesAsync_CoversAllScenarios(string compType)
280289
displayPackagesInfo.JfrogFoundPackagesPython = new List<ComponentsToArtifactory>();
281290
displayPackagesInfo.JfrogFoundPackagesConan = new List<ComponentsToArtifactory>();
282291
displayPackagesInfo.JfrogFoundPackagesDebian = new List<ComponentsToArtifactory>();
292+
displayPackagesInfo.JfrogFoundPackagesCargo = new List<ComponentsToArtifactory>();
283293
var operationType = "operationType";
284294
var responseMessage = new HttpResponseMessage();
285295
var dryRunSuffix = "dryRunSuffix";
@@ -318,6 +328,234 @@ public async Task JfrogFoundPackagesAsync_CoversAllScenarios(string compType)
318328
Assert.AreEqual(1, displayPackagesInfo.JfrogFoundPackagesDebian.Count);
319329
Assert.That(displayPackagesInfo.JfrogFoundPackagesDebian[0], Is.Not.Null);
320330
}
331+
else if (item.ComponentType == "CARGO")
332+
{
333+
Assert.AreEqual(1, displayPackagesInfo.JfrogFoundPackagesCargo.Count);
334+
Assert.That(displayPackagesInfo.JfrogFoundPackagesCargo[0], Is.Not.Null);
335+
}
336+
}
337+
338+
[Test]
339+
public async Task JfrogNotFoundPackagesAsync_CargoComponent_AddsToCargoNotFoundList()
340+
{
341+
// Arrange
342+
var cargoItem = new ComponentsToArtifactory
343+
{
344+
ComponentType = "CARGO",
345+
Name = "serde",
346+
Version = "1.0.150",
347+
Purl = "pkg:cargo/[email protected]",
348+
SrcRepoName = "cargo-src-repo",
349+
DestRepoName = "cargo-dest-repo",
350+
PackageType = PackageType.ClearedThirdParty
351+
};
352+
var displayPackagesInfo = new DisplayPackagesInfo();
353+
displayPackagesInfo.JfrogNotFoundPackagesCargo = new List<ComponentsToArtifactory>();
354+
355+
// Act
356+
await PackageUploadHelper.JfrogNotFoundPackagesAsync(cargoItem, displayPackagesInfo);
357+
358+
// Assert
359+
Assert.AreEqual(1, displayPackagesInfo.JfrogNotFoundPackagesCargo.Count);
360+
var addedComponent = displayPackagesInfo.JfrogNotFoundPackagesCargo[0];
361+
Assert.AreEqual("serde", addedComponent.Name);
362+
Assert.AreEqual("1.0.150", addedComponent.Version);
363+
Assert.AreEqual("pkg:cargo/[email protected]", addedComponent.Purl);
364+
Assert.AreEqual("cargo-src-repo", addedComponent.SrcRepoName);
365+
Assert.AreEqual(PackageType.ClearedThirdParty, addedComponent.PackageType);
366+
}
367+
368+
[Test]
369+
public async Task JfrogFoundPackagesAsync_CargoComponent_AddsToCargoFoundList()
370+
{
371+
// Arrange
372+
var cargoItem = new ComponentsToArtifactory
373+
{
374+
ComponentType = "CARGO",
375+
Name = "tokio",
376+
Version = "1.23.0",
377+
Purl = "pkg:cargo/[email protected]",
378+
SrcRepoName = "cargo-src-repo",
379+
DestRepoName = "cargo-dest-repo",
380+
Token = "test-token",
381+
CopyPackageApiUrl = "https://test.api.url",
382+
PackageName = "tokio-1.23.0.crate",
383+
PackageType = PackageType.ClearedThirdParty
384+
};
385+
var displayPackagesInfo = new DisplayPackagesInfo();
386+
displayPackagesInfo.JfrogFoundPackagesCargo = new List<ComponentsToArtifactory>();
387+
var operationType = "copy";
388+
var responseMessage = new HttpResponseMessage(System.Net.HttpStatusCode.OK);
389+
var dryRunSuffix = "";
390+
391+
// Act
392+
await PackageUploadHelper.JfrogFoundPackagesAsync(cargoItem, displayPackagesInfo, operationType, responseMessage, dryRunSuffix);
393+
394+
// Assert
395+
Assert.AreEqual(1, displayPackagesInfo.JfrogFoundPackagesCargo.Count);
396+
var addedComponent = displayPackagesInfo.JfrogFoundPackagesCargo[0];
397+
Assert.AreEqual("tokio", addedComponent.Name);
398+
Assert.AreEqual("1.23.0", addedComponent.Version);
399+
Assert.AreEqual("pkg:cargo/[email protected]", addedComponent.Purl);
400+
Assert.AreEqual("cargo-src-repo", addedComponent.SrcRepoName);
401+
Assert.AreEqual("cargo-dest-repo", addedComponent.DestRepoName);
402+
Assert.AreEqual("copy", addedComponent.OperationType);
403+
Assert.AreEqual(responseMessage, addedComponent.ResponseMessage);
404+
Assert.AreEqual("test-token", addedComponent.Token);
405+
Assert.AreEqual("tokio-1.23.0.crate", addedComponent.PackageName);
406+
Assert.AreEqual(PackageType.ClearedThirdParty, addedComponent.PackageType);
407+
}
408+
409+
[Test]
410+
public void GetPackageNameExtensionBasedOnComponentType_CargoComponent_ReturnsCorrectExtension()
411+
{
412+
// Arrange
413+
var cargoPackage = new ComponentsToArtifactory
414+
{
415+
ComponentType = "CARGO"
416+
};
417+
418+
// Act
419+
var extension = PackageUploadHelper.GetPackageNameExtensionBasedOnComponentType(cargoPackage);
420+
421+
// Assert
422+
Assert.AreEqual(".crate", extension);
423+
}
424+
425+
[Test]
426+
public void GetPackageNameExtensionBasedOnComponentType_CargoComponentCaseInsensitive_ReturnsCorrectExtension()
427+
{
428+
// Arrange
429+
var cargoPackage = new ComponentsToArtifactory
430+
{
431+
ComponentType = "cargo" // lowercase
432+
};
433+
434+
// Act
435+
var extension = PackageUploadHelper.GetPackageNameExtensionBasedOnComponentType(cargoPackage);
436+
437+
// Assert
438+
Assert.AreEqual(".crate", extension);
439+
}
440+
441+
[Test]
442+
public void JfrogNotFoundPackagesAsync_CargoComponentWithNullDisplayInfo_ThrowsNullReferenceException()
443+
{
444+
// Arrange
445+
var cargoItem = new ComponentsToArtifactory
446+
{
447+
ComponentType = "CARGO",
448+
Name = "regex",
449+
Version = "1.7.0"
450+
};
451+
452+
// Act & Assert
453+
Assert.ThrowsAsync<System.NullReferenceException>(async () =>
454+
await PackageUploadHelper.JfrogNotFoundPackagesAsync(cargoItem, null));
455+
}
456+
457+
[Test]
458+
public void JfrogFoundPackagesAsync_CargoComponentWithNullDisplayInfo_ThrowsNullReferenceException()
459+
{
460+
// Arrange
461+
var cargoItem = new ComponentsToArtifactory
462+
{
463+
ComponentType = "CARGO",
464+
Name = "clap",
465+
Version = "4.0.0"
466+
};
467+
var operationType = "move";
468+
var responseMessage = new HttpResponseMessage(System.Net.HttpStatusCode.OK);
469+
var dryRunSuffix = "";
470+
471+
// Act & Assert
472+
Assert.ThrowsAsync<System.NullReferenceException>(async () =>
473+
await PackageUploadHelper.JfrogFoundPackagesAsync(cargoItem, null, operationType, responseMessage, dryRunSuffix));
474+
}
475+
476+
[Test]
477+
public async Task JfrogFoundPackagesAsync_CargoComponentWithNullResponseMessage_StillAddsToList()
478+
{
479+
// Arrange
480+
var cargoItem = new ComponentsToArtifactory
481+
{
482+
ComponentType = "CARGO",
483+
Name = "rand",
484+
Version = "0.8.5"
485+
};
486+
var displayPackagesInfo = new DisplayPackagesInfo();
487+
displayPackagesInfo.JfrogFoundPackagesCargo = new List<ComponentsToArtifactory>();
488+
var operationType = "copy";
489+
HttpResponseMessage responseMessage = null;
490+
var dryRunSuffix = "dry-run";
491+
492+
// Act
493+
await PackageUploadHelper.JfrogFoundPackagesAsync(cargoItem, displayPackagesInfo, operationType, responseMessage, dryRunSuffix);
494+
495+
// Assert
496+
Assert.AreEqual(1, displayPackagesInfo.JfrogFoundPackagesCargo.Count);
497+
var addedComponent = displayPackagesInfo.JfrogFoundPackagesCargo[0];
498+
Assert.AreEqual("rand", addedComponent.Name);
499+
Assert.AreEqual("0.8.5", addedComponent.Version);
500+
Assert.AreEqual("copy", addedComponent.OperationType);
501+
Assert.IsNull(addedComponent.ResponseMessage);
502+
Assert.AreEqual("dry-run", addedComponent.DryRunSuffix);
503+
}
504+
505+
[Test]
506+
public async Task JfrogNotFoundPackagesAsync_CargoComponentWithEmptyName_AddsComponentWithEmptyName()
507+
{
508+
// Arrange
509+
var cargoItem = new ComponentsToArtifactory
510+
{
511+
ComponentType = "CARGO",
512+
Name = "",
513+
Version = "1.0.0",
514+
Purl = "pkg:cargo/@1.0.0"
515+
};
516+
var displayPackagesInfo = new DisplayPackagesInfo();
517+
displayPackagesInfo.JfrogNotFoundPackagesCargo = new List<ComponentsToArtifactory>();
518+
519+
// Act
520+
await PackageUploadHelper.JfrogNotFoundPackagesAsync(cargoItem, displayPackagesInfo);
521+
522+
// Assert
523+
Assert.AreEqual(1, displayPackagesInfo.JfrogNotFoundPackagesCargo.Count);
524+
var addedComponent = displayPackagesInfo.JfrogNotFoundPackagesCargo[0];
525+
Assert.AreEqual("", addedComponent.Name);
526+
Assert.AreEqual("1.0.0", addedComponent.Version);
527+
}
528+
529+
[Test]
530+
public async Task JfrogFoundPackagesAsync_CargoComponentMultipleCalls_AddsMultipleComponents()
531+
{
532+
// Arrange
533+
var cargoItem1 = new ComponentsToArtifactory
534+
{
535+
ComponentType = "CARGO",
536+
Name = "serde",
537+
Version = "1.0.150"
538+
};
539+
var cargoItem2 = new ComponentsToArtifactory
540+
{
541+
ComponentType = "CARGO",
542+
Name = "tokio",
543+
Version = "1.23.0"
544+
};
545+
var displayPackagesInfo = new DisplayPackagesInfo();
546+
displayPackagesInfo.JfrogFoundPackagesCargo = new List<ComponentsToArtifactory>();
547+
var operationType = "move";
548+
var responseMessage = new HttpResponseMessage(System.Net.HttpStatusCode.OK);
549+
var dryRunSuffix = "";
550+
551+
// Act
552+
await PackageUploadHelper.JfrogFoundPackagesAsync(cargoItem1, displayPackagesInfo, operationType, responseMessage, dryRunSuffix);
553+
await PackageUploadHelper.JfrogFoundPackagesAsync(cargoItem2, displayPackagesInfo, operationType, responseMessage, dryRunSuffix);
554+
555+
// Assert
556+
Assert.AreEqual(2, displayPackagesInfo.JfrogFoundPackagesCargo.Count);
557+
Assert.AreEqual("serde", displayPackagesInfo.JfrogFoundPackagesCargo[0].Name);
558+
Assert.AreEqual("tokio", displayPackagesInfo.JfrogFoundPackagesCargo[1].Name);
321559
}
322560

323561

0 commit comments

Comments
 (0)