diff --git a/src/AritfactoryUploader.UTest/ArtifactoryUploaderTest.cs b/src/AritfactoryUploader.UTest/ArtifactoryUploaderTest.cs index 952868eac..f3d15c86c 100644 --- a/src/AritfactoryUploader.UTest/ArtifactoryUploaderTest.cs +++ b/src/AritfactoryUploader.UTest/ArtifactoryUploaderTest.cs @@ -23,16 +23,16 @@ using System.Threading.Tasks; using UnitTestUtilities; -namespace AritfactoryUploader.UTest +namespace LCT.ArtifactoryUploader.UTest { [TestFixture] - public class ArtifactoryUploader + public class ArtifactoryUploaderTests { [Test] public void GettPathForArtifactoryUpload_ReturnsValidPath() { // Act - var result = ArtfactoryUploader.GettPathForArtifactoryUpload(); + var result = ArtifactoryUploader.GettPathForArtifactoryUpload(); // Assert Assert.IsNotNull(result); Assert.IsTrue(result.Contains("ClearingTool")); @@ -63,7 +63,7 @@ public void Setup() [Test] - public async Task UploadPackageToRepo_InputEmptyCreds_ReturnsPackgeNotFound() + public async Task UploadPackageToRepo_InputEmptyCreds_ReturnsPackageNotFound() { //Arrange CommonAppSettings appSettings = new CommonAppSettings(); @@ -72,7 +72,7 @@ public async Task UploadPackageToRepo_InputEmptyCreds_ReturnsPackgeNotFound() URL = UTParams.JFrogURL }; - ArtfactoryUploader.JFrogService = GetJfrogService(appSettings); + ArtifactoryUploader.JFrogService = GetJfrogService(appSettings); DisplayPackagesInfo displayPackagesInfo = PackageUploadInformation.GetComponentsToBePackages(); var componentsToArtifactory = new ComponentsToArtifactory { @@ -94,7 +94,7 @@ public async Task UploadPackageToRepo_InputEmptyCreds_ReturnsPackgeNotFound() }; //Act - var responseMessage = await ArtfactoryUploader.UploadPackageToRepo(componentsToArtifactory, 100, displayPackagesInfo); + var responseMessage = await ArtifactoryUploader.UploadPackageToRepo(componentsToArtifactory, 100, displayPackagesInfo); Assert.AreEqual(HttpStatusCode.NotFound, responseMessage.StatusCode); Assert.AreEqual("Package Not Found", responseMessage.ReasonPhrase); @@ -128,9 +128,9 @@ public async Task UploadPackageToRepo_WhenPackageInfoIsNull_ReturnsNotFoundRespo var jFrogServiceMock = new Mock(); jFrogServiceMock.Setup(x => x.GetPackageInfo(component)) .ReturnsAsync((AqlResult)null); - ArtfactoryUploader.JFrogService = jFrogServiceMock.Object; + ArtifactoryUploader.JFrogService = jFrogServiceMock.Object; // Act - var response = await ArtfactoryUploader.UploadPackageToRepo(component, timeout, displayPackagesInfo); + var response = await ArtifactoryUploader.UploadPackageToRepo(component, timeout, displayPackagesInfo); // Assert Assert.AreEqual(HttpStatusCode.NotFound, response.StatusCode); @@ -158,10 +158,10 @@ public async Task UploadPackageToRepo_WhenPackageTypeIsClearedThirdPartyOrDevelo .ReturnsAsync(new AqlResult()); jfrogApicommunicationMock.Setup(x => x.CopyFromRemoteRepo(It.IsAny())) .ReturnsAsync(new HttpResponseMessage(HttpStatusCode.OK)); - ArtfactoryUploader.JFrogService = jFrogServiceMock.Object; - ArtfactoryUploader.JFrogApiCommInstance = jfrogApicommunicationMock.Object; + ArtifactoryUploader.JFrogService = jFrogServiceMock.Object; + ArtifactoryUploader.JFrogApiCommInstance = jfrogApicommunicationMock.Object; // Act - _ = await ArtfactoryUploader.UploadPackageToRepo(component, timeout, displayPackagesInfo); + _ = await ArtifactoryUploader.UploadPackageToRepo(component, timeout, displayPackagesInfo); // Assert jfrogApicommunicationMock.Verify(x => x.CopyFromRemoteRepo(component), Times.Once); @@ -188,10 +188,10 @@ public async Task UploadPackageToRepo_WhenPackageTypeIsInternal_CallsMoveFromRep .ReturnsAsync(new AqlResult()); jfrogApicommunicationMock.Setup(x => x.MoveFromRepo(It.IsAny())) .ReturnsAsync(new HttpResponseMessage(HttpStatusCode.OK)); - ArtfactoryUploader.JFrogService = jFrogServiceMock.Object; - ArtfactoryUploader.JFrogApiCommInstance = jfrogApicommunicationMock.Object; + ArtifactoryUploader.JFrogService = jFrogServiceMock.Object; + ArtifactoryUploader.JFrogApiCommInstance = jfrogApicommunicationMock.Object; // Act - var response = await ArtfactoryUploader.UploadPackageToRepo(component, timeout, displayPackagesInfo); + var response = await ArtifactoryUploader.UploadPackageToRepo(component, timeout, displayPackagesInfo); // Assert jfrogApicommunicationMock.Verify(x => x.MoveFromRepo(component), Times.Once); @@ -214,9 +214,9 @@ public async Task UploadPackageToRepo_WhenPackageTypeIsNotSupported_ReturnsNotFo var timeout = 10000; var displayPackagesInfo = new DisplayPackagesInfo(); var jFrogServiceMock = new Mock(); - ArtfactoryUploader.JFrogService = jFrogServiceMock.Object; + ArtifactoryUploader.JFrogService = jFrogServiceMock.Object; // Act - var response = await ArtfactoryUploader.UploadPackageToRepo(component, timeout, displayPackagesInfo); + var response = await ArtifactoryUploader.UploadPackageToRepo(component, timeout, displayPackagesInfo); // Assert Assert.AreEqual(HttpStatusCode.NotFound, response.StatusCode); @@ -240,11 +240,11 @@ public async Task UploadPackageToRepo_WhenHttpRequestExceptionOccurs_ReturnsErro var jfrogApicommunicationMock = new Mock(); jFrogServiceMock.Setup(x => x.GetPackageInfo(component)) .ThrowsAsync(new HttpRequestException()); - ArtfactoryUploader.JFrogService = jFrogServiceMock.Object; - ArtfactoryUploader.JFrogApiCommInstance = jfrogApicommunicationMock.Object; + ArtifactoryUploader.JFrogService = jFrogServiceMock.Object; + ArtifactoryUploader.JFrogApiCommInstance = jfrogApicommunicationMock.Object; // Act - var response = await ArtfactoryUploader.UploadPackageToRepo(component, timeout, displayPackagesInfo); + var response = await ArtifactoryUploader.UploadPackageToRepo(component, timeout, displayPackagesInfo); // Assert Assert.AreEqual(ApiConstant.ErrorInUpload, response.ReasonPhrase); @@ -269,11 +269,11 @@ public async Task UploadPackageToRepo_WhenInvalidOperationExceptionOccurs_Return var jfrogApicommunicationMock = new Mock(); jFrogServiceMock.Setup(x => x.GetPackageInfo(component)) .ThrowsAsync(new InvalidOperationException()); - ArtfactoryUploader.JFrogService = jFrogServiceMock.Object; - ArtfactoryUploader.JFrogApiCommInstance = jfrogApicommunicationMock.Object; + ArtifactoryUploader.JFrogService = jFrogServiceMock.Object; + ArtifactoryUploader.JFrogApiCommInstance = jfrogApicommunicationMock.Object; // Act - var response = await ArtfactoryUploader.UploadPackageToRepo(component, timeout, displayPackagesInfo); + var response = await ArtifactoryUploader.UploadPackageToRepo(component, timeout, displayPackagesInfo); // Assert Assert.AreEqual(ApiConstant.ErrorInUpload, response.ReasonPhrase); @@ -313,11 +313,11 @@ public async Task UploadPackageToRepo_WhenDebianOrNugetNameMismatch_UpdatesCopyP .Setup(c => c.CopyFromRemoteRepo(component)) .ReturnsAsync(new HttpResponseMessage(HttpStatusCode.OK)); - ArtfactoryUploader.JFrogService = jfrogServiceMock.Object; - ArtfactoryUploader.JFrogApiCommInstance = jfrogApiCommMock.Object; + ArtifactoryUploader.JFrogService = jfrogServiceMock.Object; + ArtifactoryUploader.JFrogApiCommInstance = jfrogApiCommMock.Object; // Act - var response = await ArtfactoryUploader.UploadPackageToRepo(component, timeout, displayPackagesInfo); + var response = await ArtifactoryUploader.UploadPackageToRepo(component, timeout, displayPackagesInfo); // Assert Assert.AreEqual(HttpStatusCode.OK, response.StatusCode, "Expected successful copy response."); diff --git a/src/AritfactoryUploader.UTest/AritfactoryUploader.UTest.csproj b/src/AritfactoryUploader.UTest/LCT.ArtifactoryUploader.UTest.csproj similarity index 100% rename from src/AritfactoryUploader.UTest/AritfactoryUploader.UTest.csproj rename to src/AritfactoryUploader.UTest/LCT.ArtifactoryUploader.UTest.csproj diff --git a/src/AritfactoryUploader.UTest/PackageUploaderTest.cs b/src/AritfactoryUploader.UTest/PackageUploaderTest.cs index f0032e460..ca8ec1101 100644 --- a/src/AritfactoryUploader.UTest/PackageUploaderTest.cs +++ b/src/AritfactoryUploader.UTest/PackageUploaderTest.cs @@ -4,11 +4,10 @@ // SPDX-License-Identifier: MIT // -------------------------------------------------------------------------------------------------------------------- -using ArtifactoryUploader; +using LCT.ArtifactoryUploader; using LCT.APICommunications; using LCT.APICommunications.Interfaces; using LCT.APICommunications.Model; -using LCT.ArtifactoryUploader; using LCT.Common; using LCT.Common.Model; using LCT.Facade; @@ -22,7 +21,7 @@ using System.Threading.Tasks; using UnitTestUtilities; -namespace AritfactoryUploader.UTest +namespace LCT.ArtifactoryUploader.UTest { [TestFixture] public class PackageUploaderTest @@ -76,7 +75,7 @@ public async Task UploadPackageToArtifactory_GivenAppsettings() IJFrogService jFrogService = GetJfrogService(commonAppSettings); PackageUploadHelper.JFrogService = jFrogService; UploadToArtifactory.JFrogService = jFrogService; - ArtfactoryUploader.JFrogService = jFrogService; + ArtifactoryUploader.JFrogService = jFrogService; Program.UploaderStopWatch = new Stopwatch(); Program.UploaderStopWatch.Start(); diff --git a/src/ArtifactoryUploader/ArtifactoryUploader.cs b/src/ArtifactoryUploader/ArtifactoryUploader.cs index 2e78558c6..567d9a414 100644 --- a/src/ArtifactoryUploader/ArtifactoryUploader.cs +++ b/src/ArtifactoryUploader/ArtifactoryUploader.cs @@ -22,13 +22,31 @@ namespace LCT.ArtifactoryUploader { - public static class ArtfactoryUploader + public static class ArtifactoryUploader { - //ConfigurationAttribute + #region Fields + static readonly ILog Logger = LoggerFactory.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + #endregion + + #region Properties + public static IJFrogService JFrogService { get; set; } public static IJFrogApiCommunication JFrogApiCommInstance { get; set; } + #endregion + + #region Methods + + /// + /// Asynchronously uploads a package to the repository. + /// + /// The component to upload. + /// The timeout value in seconds. + /// The display information for packages. + /// A task containing the HTTP response message. + public static async Task UploadPackageToRepo(ComponentsToArtifactory component, int timeout, DisplayPackagesInfo displayPackagesInfo) { @@ -77,6 +95,11 @@ public static async Task UploadPackageToRepo(ComponentsToAr return responsemessage; } + /// + /// Gets the operation type for the component based on package type. + /// + /// The component to determine operation type for. + /// The operation type as a string ("copy" or "move"). private static string GetOperationType(ComponentsToArtifactory component) { if (component.ComponentType == "CHOCO") @@ -86,6 +109,11 @@ private static string GetOperationType(ComponentsToArtifactory component) return (component.PackageType == PackageType.ClearedThirdParty || component.PackageType == PackageType.Development) ? "copy" : "move"; } + /// + /// Asynchronously gets the repository operation response based on package type. + /// + /// The component to perform the operation on. + /// A task containing the HTTP response message. private static async Task GetRepoOperationResponse(ComponentsToArtifactory component) { return component.PackageType switch @@ -98,6 +126,11 @@ await JFrogApiCommInstance.MoveFromRepo(component), }; } + /// + /// Creates a not found HTTP response message. + /// + /// The reason phrase for the response. + /// An HTTP response message with not found status. private static HttpResponseMessage CreateNotFoundResponse(string reasonPhrase) { return new HttpResponseMessage(HttpStatusCode.NotFound) @@ -106,6 +139,12 @@ private static HttpResponseMessage CreateNotFoundResponse(string reasonPhrase) }; } + /// + /// Handles upload exceptions and returns an error response. + /// + /// The exception that occurred. + /// The response message to update. + /// An HTTP response message with error information. private static HttpResponseMessage HandleUploadException(Exception ex, HttpResponseMessage responsemessage) { Logger.Error("Error has occurred in UploadPackageToArtifactory--{Exception}", ex); @@ -113,6 +152,12 @@ private static HttpResponseMessage HandleUploadException(Exception ex, HttpRespo return responsemessage; } + /// + /// Asynchronously gets package information with retry logic for lowercase names. + /// + /// The JFrog service instance. + /// The component to get information for. + /// A task containing the AQL result with package information, or null if not found. private static async Task GetPackageInfoWithRetry(IJFrogService jFrogService, ComponentsToArtifactory component) { async Task TryGetPackageInfo(ComponentsToArtifactory component) @@ -145,6 +190,11 @@ async Task TryGetPackageInfo(ComponentsToArtifactory component) return packageInfo; } + + /// + /// Gets the path for Artifactory upload directory. + /// + /// The local path for Artifactory upload. public static string GettPathForArtifactoryUpload() { string localPathforartifactory = string.Empty; @@ -169,5 +219,6 @@ public static string GettPathForArtifactoryUpload() return localPathforartifactory; } + #endregion } } diff --git a/src/ArtifactoryUploader/ArtifactoryValidator.cs b/src/ArtifactoryUploader/ArtifactoryValidator.cs index 770c5a7ef..3d867d0cd 100644 --- a/src/ArtifactoryUploader/ArtifactoryValidator.cs +++ b/src/ArtifactoryUploader/ArtifactoryValidator.cs @@ -13,13 +13,31 @@ namespace LCT.ArtifactoryUploader { public class ArtifactoryValidator { + #region Fields + private readonly IJfrogAqlApiCommunication _JfrogAqlApiCommunication; + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the ArtifactoryValidator class. + /// + /// The JFrog AQL API communication instance. public ArtifactoryValidator(IJfrogAqlApiCommunication jfrogAqlApiCommunication) { _JfrogAqlApiCommunication = jfrogAqlApiCommunication; } + #endregion + + #region Methods + + /// + /// Asynchronously validates Artifactory credentials by checking the connection. + /// + /// A task containing 0 if validation succeeds, -1 if validation fails. public async Task ValidateArtifactoryCredentials() { HttpResponseMessage responseMessage = new HttpResponseMessage(); @@ -37,5 +55,7 @@ public async Task ValidateArtifactoryCredentials() return -1; } } + + #endregion } } diff --git a/src/ArtifactoryUploader/Constants/ArtifactoryConstant.cs b/src/ArtifactoryUploader/Constants/ArtifactoryConstant.cs index 91348104c..2c8326720 100644 --- a/src/ArtifactoryUploader/Constants/ArtifactoryConstant.cs +++ b/src/ArtifactoryUploader/Constants/ArtifactoryConstant.cs @@ -14,6 +14,10 @@ namespace ArtifactoryUploader.Constants [ExcludeFromCodeCoverage] public static class ArtifactoryConstant { + #region Fields + public const string Log4netArtifactoryUploaderConfigFileName = "log4netArtifactoryUploader.config"; + + #endregion } } diff --git a/src/ArtifactoryUploader/JfrogRepoUpdater.cs b/src/ArtifactoryUploader/JfrogRepoUpdater.cs index 7745edb1c..348148028 100644 --- a/src/ArtifactoryUploader/JfrogRepoUpdater.cs +++ b/src/ArtifactoryUploader/JfrogRepoUpdater.cs @@ -19,8 +19,26 @@ namespace LCT.ArtifactoryUploader { public static class JfrogRepoUpdater { - public static IJFrogService JFrogService { get; set; } + #region Fields + private readonly static List aqlResultList = new(); + + #endregion + + #region Properties + + public static IJFrogService JFrogService { get; set; } + + #endregion + + #region Methods + + /// + /// Asynchronously updates JFrog repository path for successfully uploaded items. + /// + /// The BOM containing components. + /// The display information for packages. + /// A task containing the updated BOM. public static async Task UpdateJfrogRepoPathForSucessfullyUploadedItems(Bom m_ComponentsInBOM, DisplayPackagesInfo displayPackagesInfo) { @@ -37,6 +55,14 @@ public static async Task UpdateJfrogRepoPathForSucessfullyUploadedItems(Bom return m_ComponentsInBOM; } + + /// + /// Updates the JFrog repository path property for BOM components. + /// + /// The BOM containing components. + /// The list of uploaded packages. + /// The list of JFrog packages from AQL query. + /// A list of updated components. private static List UpdateJfroRepoPathProperty(Bom m_ComponentsInBOM, List uploadedPackages, List jfrogPackagesListAql) @@ -83,6 +109,12 @@ private static List UpdateJfroRepoPathProperty(Bom m_ComponentsInBOM, return bomComponents; } + + /// + /// Gets the JFrog repository path from AQL result. + /// + /// The AQL result containing repository information. + /// The formatted JFrog repository path. private static string GetJfrogRepoPath(AqlResult aqlResult) { if (string.IsNullOrEmpty(aqlResult.Path) || aqlResult.Path.Equals(".")) @@ -91,6 +123,14 @@ private static string GetJfrogRepoPath(AqlResult aqlResult) } return $"{aqlResult.Repo}/{aqlResult.Path}/{aqlResult.Name}"; } + + /// + /// Gets the JFrog information of the uploaded package from AQL results. + /// + /// The list of JFrog packages from AQL query. + /// The package to find information for. + /// The package name extension. + /// The AQL result for the uploaded package, or null if not found. private static AqlResult GetJfrogInfoOfThePackageUploaded(List jfrogPackagesListAql, ComponentsToArtifactory package, string packageNameEXtension) { string pkgType = package.ComponentType ?? string.Empty; @@ -105,6 +145,11 @@ private static AqlResult GetJfrogInfoOfThePackageUploaded(List jfrogP && x.Name.Contains(packageNameEXtension)); } + /// + /// Asynchronously gets JFrog repository information for all package types. + /// + /// The list of destination repository names. + /// A task containing a list of AQL results for all packages. public static async Task> GetJfrogRepoInfoForAllTypePackages(List destRepoNames) { if (destRepoNames != null && destRepoNames.Count > 0) @@ -119,5 +164,6 @@ public static async Task> GetJfrogRepoInfoForAllTypePackages(Lis return aqlResultList; } + #endregion } } diff --git a/src/ArtifactoryUploader/Model/DisplayPackagesInfo.cs b/src/ArtifactoryUploader/Model/DisplayPackagesInfo.cs index 2fe020281..ed0bd742d 100644 --- a/src/ArtifactoryUploader/Model/DisplayPackagesInfo.cs +++ b/src/ArtifactoryUploader/Model/DisplayPackagesInfo.cs @@ -16,6 +16,8 @@ namespace LCT.ArtifactoryUploader.Model [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class DisplayPackagesInfo { + #region Properties + public List UnknownPackagesNpm { get; set; } public List UnknownPackagesNuget { get; set; } public List UnknownPackagesConan { get; set; } @@ -49,9 +51,16 @@ public class DisplayPackagesInfo public List SuccessfullPackagesCargo { get; set; } public List SuccessfullPackagesChoco { get; set; } + #endregion } + + /// + /// The Model class for ProjectResponse + /// public class ProjectResponse { + #region Properties + [JsonProperty("npm")] public List Npm { get; set; } [JsonProperty("nuget")] @@ -68,13 +77,22 @@ public class ProjectResponse public List Cargo { get; set; } [JsonProperty("choco")] public List Choco { get; set; } + + #endregion } + /// + /// The Model class for JsonComponents + /// public class JsonComponents { + #region Properties + [JsonProperty("name")] public string Name { get; set; } [JsonProperty("version")] public string Version { get; set; } + + #endregion } } diff --git a/src/ArtifactoryUploader/Model/JfrogKey.cs b/src/ArtifactoryUploader/Model/JfrogKey.cs index 7319901ca..2f87b4545 100644 --- a/src/ArtifactoryUploader/Model/JfrogKey.cs +++ b/src/ArtifactoryUploader/Model/JfrogKey.cs @@ -13,6 +13,10 @@ namespace LCT.ArtifactoryUploader.Model [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class JfrogKey { + #region Properties + public string Token { get; set; } + + #endregion } } diff --git a/src/ArtifactoryUploader/Model/UploaderKpiData.cs b/src/ArtifactoryUploader/Model/UploaderKpiData.cs index 3cc0213be..148dd6e24 100644 --- a/src/ArtifactoryUploader/Model/UploaderKpiData.cs +++ b/src/ArtifactoryUploader/Model/UploaderKpiData.cs @@ -15,6 +15,8 @@ namespace LCT.ArtifactoryUploader.Model [ExcludeFromCodeCoverage] public class UploaderKpiData { + #region Properties + [DisplayName(@"Components in BoM")] public int ComponentInComparisonBOM { get; set; } @@ -51,5 +53,6 @@ public class UploaderKpiData [DisplayName(@"Packages Not Moved to Repo")] public int InternalPackagesNotUploadedToJfrog { get; set; } + #endregion } } diff --git a/src/ArtifactoryUploader/PackageUploadHelper.cs b/src/ArtifactoryUploader/PackageUploadHelper.cs index 64da9b79e..5eef04470 100644 --- a/src/ArtifactoryUploader/PackageUploadHelper.cs +++ b/src/ArtifactoryUploader/PackageUploadHelper.cs @@ -6,7 +6,6 @@ // Ignore Spelling: Artifactory Bom Repo uploader Kpi Jfrog Api LCT aql -using ArtifactoryUploader; using CycloneDX.Models; using LCT.APICommunications; using LCT.APICommunications.Interfaces; @@ -35,10 +34,27 @@ namespace LCT.ArtifactoryUploader /// public static class PackageUploadHelper { + #region Fields + static readonly ILog Logger = LoggerFactory.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static bool SetWarningCode; + + #endregion + + #region Properties + public static IJFrogService JFrogService { get; set; } - private static bool SetWarningCode; + #endregion + + #region Methods + + /// + /// Gets the component list from the comparison BOM file. + /// + /// The file path to the comparison BOM. + /// The environment helper for exit operations. + /// A Bom object containing the components. public static Bom GetComponentListFromComparisonBOM(string comparisonBomFilePath, IEnvironmentHelper environmentHelper) { Logger.Debug("GetComponentListFromComparisonBOM(): Reading bom file for components."); @@ -67,6 +83,14 @@ public static Bom GetComponentListFromComparisonBOM(string comparisonBomFilePath return componentsToBoms; } + /// + /// Gets package information with operation details and response message. + /// + /// The component to get information for. + /// The type of operation performed. + /// The HTTP response message. + /// The suffix for dry run mode. + /// A task containing the components to Artifactory information. private static Task GetPackageinfo(ComponentsToArtifactory item, string operationType, HttpResponseMessage responseMessage, string dryRunSuffix) { @@ -90,6 +114,12 @@ private static Task GetPackageinfo(ComponentsToArtifact return Task.FromResult(components); } + + /// + /// Gets successful package information from a component. + /// + /// The component to get information for. + /// A task containing the components to Artifactory information. private static Task GetSucessFulPackageinfo(ComponentsToArtifactory item) { @@ -110,24 +140,53 @@ private static Task GetSucessFulPackageinfo(ComponentsT } + /// + /// Asynchronously processes packages not found in JFrog. + /// + /// The component to process. + /// The display information for packages. + /// A task representing the asynchronous operation. public static async Task JfrogNotFoundPackagesAsync(ComponentsToArtifactory item, DisplayPackagesInfo displayPackagesInfo) { ComponentsToArtifactory components = await GetSucessFulPackageinfo(item); AddComponentToDisplayList(item.ComponentType, components, displayPackagesInfo, notFound: true); } + /// + /// Asynchronously processes packages found in JFrog. + /// + /// The component to process. + /// The display information for packages. + /// The type of operation performed. + /// The HTTP response message. + /// The suffix for dry run mode. + /// A task representing the asynchronous operation. public static async Task JfrogFoundPackagesAsync(ComponentsToArtifactory item, DisplayPackagesInfo displayPackagesInfo, string operationType, HttpResponseMessage responseMessage, string dryRunSuffix) { ComponentsToArtifactory components = await GetPackageinfo(item, operationType, responseMessage, dryRunSuffix); AddComponentToDisplayList(item.ComponentType, components, displayPackagesInfo, notFound: false); } + + /// + /// Asynchronously processes successfully uploaded packages. + /// + /// The component to process. + /// The display information for packages. + /// A task representing the asynchronous operation. private static async Task SucessfullPackagesAsync(ComponentsToArtifactory item, DisplayPackagesInfo displayPackagesInfo) { ComponentsToArtifactory components = await GetSucessFulPackageinfo(item); AddComponentToDisplayList(item.ComponentType, components, displayPackagesInfo, success: true); } - // Helper to reduce code duplication for adding components to display lists + /// + /// Adds a component to the appropriate display list based on its type and status. + /// + /// The type of the component. + /// The component to add. + /// The display information for packages. + /// Whether the package was not found. + /// Whether the package was successfully processed. private static void AddComponentToDisplayList(string componentType, ComponentsToArtifactory component, DisplayPackagesInfo displayPackagesInfo, bool notFound = false, bool success = false) { if (string.IsNullOrWhiteSpace(componentType)) @@ -162,6 +221,13 @@ private static void AddComponentToDisplayList(string componentType, ComponentsTo } } + /// + /// Adds a component to the NPM display list. + /// + /// The component to add. + /// The display information for packages. + /// Whether the package was not found. + /// Whether the package was successfully processed. private static void AddToNpmList(ComponentsToArtifactory component, DisplayPackagesInfo displayPackagesInfo, bool notFound, bool success) { if (notFound) @@ -172,6 +238,13 @@ private static void AddToNpmList(ComponentsToArtifactory component, DisplayPacka displayPackagesInfo.JfrogFoundPackagesNpm.Add(component); } + /// + /// Adds a component to the NuGet display list. + /// + /// The component to add. + /// The display information for packages. + /// Whether the package was not found. + /// Whether the package was successfully processed. private static void AddToNugetList(ComponentsToArtifactory component, DisplayPackagesInfo displayPackagesInfo, bool notFound, bool success) { if (notFound) @@ -182,6 +255,13 @@ private static void AddToNugetList(ComponentsToArtifactory component, DisplayPac displayPackagesInfo.JfrogFoundPackagesNuget.Add(component); } + /// + /// Adds a component to the Maven display list. + /// + /// The component to add. + /// The display information for packages. + /// Whether the package was not found. + /// Whether the package was successfully processed. private static void AddToMavenList(ComponentsToArtifactory component, DisplayPackagesInfo displayPackagesInfo, bool notFound, bool success) { if (notFound) @@ -192,6 +272,13 @@ private static void AddToMavenList(ComponentsToArtifactory component, DisplayPac displayPackagesInfo.JfrogFoundPackagesMaven.Add(component); } + /// + /// Adds a component to the Poetry display list. + /// + /// The component to add. + /// The display information for packages. + /// Whether the package was not found. + /// Whether the package was successfully processed. private static void AddToPoetryList(ComponentsToArtifactory component, DisplayPackagesInfo displayPackagesInfo, bool notFound, bool success) { if (notFound) @@ -202,6 +289,13 @@ private static void AddToPoetryList(ComponentsToArtifactory component, DisplayPa displayPackagesInfo.JfrogFoundPackagesPython.Add(component); } + /// + /// Adds a component to the Conan display list. + /// + /// The component to add. + /// The display information for packages. + /// Whether the package was not found. + /// Whether the package was successfully processed. private static void AddToConanList(ComponentsToArtifactory component, DisplayPackagesInfo displayPackagesInfo, bool notFound, bool success) { if (notFound) @@ -212,6 +306,13 @@ private static void AddToConanList(ComponentsToArtifactory component, DisplayPac displayPackagesInfo.JfrogFoundPackagesConan.Add(component); } + /// + /// Adds a component to the Debian display list. + /// + /// The component to add. + /// The display information for packages. + /// Whether the package was not found. + /// Whether the package was successfully processed. private static void AddToDebianList(ComponentsToArtifactory component, DisplayPackagesInfo displayPackagesInfo, bool notFound, bool success) { if (notFound) @@ -222,6 +323,13 @@ private static void AddToDebianList(ComponentsToArtifactory component, DisplayPa displayPackagesInfo.JfrogFoundPackagesDebian.Add(component); } + /// + /// Adds a component to the Cargo display list. + /// + /// The component to add. + /// The display information for packages. + /// Whether the package was not found. + /// Whether the package was successfully processed. private static void AddToCargoList(ComponentsToArtifactory component, DisplayPackagesInfo displayPackagesInfo, bool notFound, bool success) { if (notFound) @@ -231,6 +339,15 @@ private static void AddToCargoList(ComponentsToArtifactory component, DisplayPac else displayPackagesInfo.JfrogFoundPackagesCargo.Add(component); } + + + /// + /// Asynchronously uploads the packages to Artifactory. + /// + /// The list of components to upload. + /// The timeout value in seconds. + /// The display information for packages. + /// A task representing the asynchronous operation. private static void AddToChocoList(ComponentsToArtifactory component, DisplayPackagesInfo displayPackagesInfo, bool notFound, bool success) { if (notFound) @@ -260,6 +377,14 @@ public static async Task UploadingThePackages(List comp Program.UploaderStopWatch?.Stop(); } + /// + /// Asynchronously uploads a package to Artifactory. + /// + /// The uploader KPI data for tracking. + /// The component to upload. + /// The timeout value in seconds. + /// The display information for packages. + /// A task representing the asynchronous operation. private static async Task PackageUploadToArtifactory(UploaderKpiData uploaderKpiData, ComponentsToArtifactory item, int timeout, @@ -292,13 +417,22 @@ private static async Task PackageUploadToArtifactory(UploaderKpiData uploaderKpi } } + /// + /// Asynchronously uploads a package when the source repository is found. + /// + /// The type of the package. + /// The uploader KPI data for tracking. + /// The component to upload. + /// The timeout value in seconds. + /// The display information for packages. + /// A task representing the asynchronous operation. private static async Task SourceRepoFoundToUploadArtifactory(PackageType packageType, UploaderKpiData uploaderKpiData, ComponentsToArtifactory item, int timeout, DisplayPackagesInfo displayPackagesInfo) { const string dryRunSuffix = null; string operationType = item.PackageType == PackageType.ClearedThirdParty || item.PackageType == PackageType.Development ? "copy" : "move"; - ArtfactoryUploader.JFrogService = JFrogService; - ArtfactoryUploader.JFrogApiCommInstance = GetJfrogApiCommInstance(item, timeout); - HttpResponseMessage responseMessage = await ArtfactoryUploader.UploadPackageToRepo(item, timeout, displayPackagesInfo); + ArtifactoryUploader.JFrogService = JFrogService; + ArtifactoryUploader.JFrogApiCommInstance = GetJfrogApiCommInstance(item, timeout); + HttpResponseMessage responseMessage = await ArtifactoryUploader.UploadPackageToRepo(item, timeout, displayPackagesInfo); if (responseMessage.StatusCode == HttpStatusCode.OK && !item.DryRun) { @@ -324,6 +458,12 @@ private static async Task SourceRepoFoundToUploadArtifactory(PackageType package // do nothing } } + + /// + /// Gets the package name extension based on the component type. + /// + /// The component package. + /// The file extension for the package type. public static string GetPackageNameExtensionBasedOnComponentType(ComponentsToArtifactory package) { string packageNameEXtension = string.Empty; @@ -358,6 +498,13 @@ public static string GetPackageNameExtensionBasedOnComponentType(ComponentsToArt return packageNameEXtension; } + + /// + /// Gets the JFrog API communication instance for the specified component. + /// + /// The component to get the API instance for. + /// The timeout value in seconds. + /// An instance of IJFrogApiCommunication. public static IJFrogApiCommunication GetJfrogApiCommInstance(ComponentsToArtifactory component, int timeout) { @@ -376,6 +523,10 @@ public static IJFrogApiCommunication GetJfrogApiCommInstance(ComponentsToArtifac return jfrogApicommunication; } + /// + /// Writes the creator KPI data to the console. + /// + /// The uploader KPI data to display. public static void WriteCreatorKpiDataToConsole(UploaderKpiData uploaderKpiData) { KpiNames uploaderKpiNames = IdentifyKpiNames(uploaderKpiData); @@ -408,6 +559,12 @@ public static void WriteCreatorKpiDataToConsole(UploaderKpiData uploaderKpiData) LoggerHelper.WriteToConsoleTable(printList, printTimingList, "", Dataconstant.Uploader, uploaderKpiNames); } + + /// + /// Identifies and maps KPI names from the uploader KPI data. + /// + /// The uploader KPI data. + /// A KpiNames object with mapped names. private static KpiNames IdentifyKpiNames(UploaderKpiData uploaderKpiData) { KpiNames uploaderKpiNames = new KpiNames(); @@ -425,6 +582,13 @@ private static KpiNames IdentifyKpiNames(UploaderKpiData uploaderKpiData) return uploaderKpiNames; } + + /// + /// Increments counters based on the package type and success status. + /// + /// The uploader KPI data to update. + /// The type of the package. + /// Whether the operation was successful. private static void IncrementCountersBasedOnPackageType(UploaderKpiData uploaderKpiData, PackageType packageType, bool isSuccess) { // Define a dictionary to map package types to counters @@ -459,6 +623,11 @@ private static void IncrementCountersBasedOnPackageType(UploaderKpiData uploader } + /// + /// Updates the BOM with Artifactory repository URLs for uploaded components. + /// + /// The BOM to update. + /// The list of uploaded components. public static void UpdateBomArtifactoryRepoUrl(ref Bom bom, List componentsUploaded) { foreach (var component in componentsUploaded) @@ -475,6 +644,7 @@ public static void UpdateBomArtifactoryRepoUrl(ref Bom bom, List + /// Gets the components to be packaged with initialized display information. + /// + /// A DisplayPackagesInfo object with initialized package lists. public static DisplayPackagesInfo GetComponentsToBePackages() { DisplayPackagesInfo displayPackagesInfo = new DisplayPackagesInfo(); @@ -67,6 +78,12 @@ public static DisplayPackagesInfo GetComponentsToBePackages() return displayPackagesInfo; } + + /// + /// Gets the uploaded package details from the display packages information. + /// + /// The display information containing all package lists. + /// A list of successfully uploaded components. public static List GetUploadePackageDetails(DisplayPackagesInfo displayPackagesInfo) { List uploadedPackages = new List(); @@ -100,9 +117,14 @@ private static void AddSuccessfulPackages(List uploaded } } } + + /// + /// Displays package upload information for all package types. + /// + /// The display information containing all package lists. public static void DisplayPackageUploadInformation(DisplayPackagesInfo displayPackagesInfo) { - string localPathforartifactory = ArtfactoryUploader.GettPathForArtifactoryUpload(); + string localPathforartifactory = ArtifactoryUploader.GettPathForArtifactoryUpload(); DisplaySortedForeachComponents(displayPackagesInfo.UnknownPackagesNpm, displayPackagesInfo.JfrogNotFoundPackagesNpm, displayPackagesInfo.SuccessfullPackagesNpm, displayPackagesInfo.JfrogFoundPackagesNpm, "npm", localPathforartifactory); DisplaySortedForeachComponents(displayPackagesInfo.UnknownPackagesNuget, displayPackagesInfo.JfrogNotFoundPackagesNuget, displayPackagesInfo.SuccessfullPackagesNuget, displayPackagesInfo.JfrogFoundPackagesNuget, "NuGet", localPathforartifactory); @@ -114,6 +136,16 @@ public static void DisplayPackageUploadInformation(DisplayPackagesInfo displayPa DisplaySortedForeachComponents(displayPackagesInfo.UnknownPackagesChoco, displayPackagesInfo.JfrogNotFoundPackagesChoco, displayPackagesInfo.SuccessfullPackagesChoco, displayPackagesInfo.JfrogFoundPackagesChoco, "Choco", localPathforartifactory); } + + /// + /// Displays sorted components for each package type based on their status. + /// + /// List of unknown packages. + /// List of packages not found in JFrog. + /// List of successfully processed packages. + /// List of packages found in JFrog. + /// The name of the package type. + /// The file path for storing package information. private static void DisplaySortedForeachComponents( List unknownPackages, List JfrogNotFoundPackages, @@ -137,11 +169,25 @@ private static void DisplaySortedForeachComponents( } } + /// + /// Checks if any of the package lists contain packages. + /// + /// Variable number of package lists to check. + /// True if any list contains packages, otherwise false. private static bool HasAnyPackages(params List[] packageLists) { return packageLists.Any(list => list?.Count > 0); } + /// + /// Displays package information using Spectre Console formatting. + /// + /// List of unknown packages. + /// List of packages not found in JFrog. + /// List of successfully processed packages. + /// List of packages found in JFrog. + /// The name of the package type. + /// The file path for storing package information. private static void DisplayWithSpectreConsole( List unknownPackages, List JfrogNotFoundPackages, @@ -159,6 +205,16 @@ private static void DisplayWithSpectreConsole( }, $"Display {name} Package Information", "Info"); } + /// + /// Appends package content to a StringBuilder for display. + /// + /// The StringBuilder to append content to. + /// List of unknown packages. + /// List of packages found in JFrog. + /// List of packages not found in JFrog. + /// List of successfully processed packages. + /// The name of the package type. + /// The file path for storing package information. private static void AppendPackageContent( StringBuilder content, List unknownPackages, @@ -172,6 +228,13 @@ private static void AppendPackageContent( AppendSuccessfulPackages(content, SucessfullPackages); } + /// + /// Appends unknown packages information to the content. + /// + /// The StringBuilder to append content to. + /// List of unknown packages. + /// The name of the package type. + /// The file path for storing package information. private static void AppendUnknownPackages(StringBuilder content, List packages, string name, string filepath) { var filename = Path.Combine(filepath, $"Artifactory_{FileConstant.artifactoryReportNotApproved}"); @@ -182,6 +245,11 @@ private static void AppendUnknownPackages(StringBuilder content, List + /// Appends JFrog found packages information to the content. + /// + /// The StringBuilder to append content to. + /// List of packages found in JFrog. private static void AppendJfrogFoundPackages(StringBuilder content, List packages) { if (packages?.Count > 0) @@ -195,6 +263,11 @@ private static void AppendJfrogFoundPackages(StringBuilder content, List + /// Formats a JFrog found package for display. + /// + /// The package to format. + /// A formatted string representation of the package. private static string FormatJfrogFoundPackage(ComponentsToArtifactory package) { if (package.ResponseMessage.ReasonPhrase == ApiConstant.ErrorInUpload) @@ -215,6 +288,11 @@ private static string FormatJfrogFoundPackage(ComponentsToArtifactory package) $"from [yellow]{package.SrcRepoName}[/] [white]⟶ [/] [yellow]{package.DestRepoName}[/]"; } + /// + /// Appends JFrog not found packages information to the content. + /// + /// The StringBuilder to append content to. + /// List of packages not found in JFrog. private static void AppendJfrogNotFoundPackages(StringBuilder content, List packages) { if (packages?.Count > 0) @@ -228,6 +306,11 @@ private static void AppendJfrogNotFoundPackages(StringBuilder content, List + /// Appends successful packages information to the content. + /// + /// The StringBuilder to append content to. + /// List of successfully processed packages. private static void AppendSuccessfulPackages(StringBuilder content, List packages) { if (packages?.Count > 0) @@ -240,6 +323,15 @@ private static void AppendSuccessfulPackages(StringBuilder content, List + /// Displays package information using standard logger. + /// + /// List of unknown packages. + /// List of packages not found in JFrog. + /// List of successfully processed packages. + /// List of packages found in JFrog. + /// The name of the package type. + /// The file path for storing package information. private static void DisplayWithLogger( List unknownPackages, List JfrogNotFoundPackages, @@ -254,6 +346,11 @@ private static void DisplayWithLogger( DisplayErrorForJfrogPackages(JfrogNotFoundPackages); DisplayErrorForSucessfullPackages(SucessfullPackages); } + + /// + /// Displays error information for packages found in JFrog. + /// + /// List of packages found in JFrog. public static void DisplayErrorForJfrogFoundPackages(List JfrogFoundPackages) { @@ -283,6 +380,10 @@ public static void DisplayErrorForJfrogFoundPackages(List + /// Displays error information for packages not found in JFrog. + /// + /// List of packages not found in JFrog. public static void DisplayErrorForJfrogPackages(List JfrogNotFoundPackages) { @@ -298,6 +399,11 @@ public static void DisplayErrorForJfrogPackages(List Jf } } + + /// + /// Displays information for successfully processed packages. + /// + /// List of successfully processed packages. private static void DisplayErrorForSucessfullPackages(List SucessfullPackages) { @@ -312,11 +418,23 @@ private static void DisplayErrorForSucessfullPackages(List + /// Displays a warning message when there are no packages to upload. + /// + /// The filename where package details can be found. private static void WarningMessageForNoPackages(string filename) { if (!LoggerFactory.UseSpectreConsole) Logger.Warn($"Artifactory upload will not be done due to Report not in Approved state and package details can be found at {filename}\n"); } + + /// + /// Displays error information for unknown packages. + /// + /// List of unknown packages. + /// The name of the package type. + /// The file path for storing package information. private static void DisplayErrorForUnknownPackages(List unknownPackages, string name, string filepath) { ProjectResponse projectResponse = new ProjectResponse(); @@ -343,6 +461,15 @@ private static void DisplayErrorForUnknownPackages(List } } } + + /// + /// Gets not approved npm packages and writes them to the report file. + /// + /// List of unknown npm packages. + /// The project response object. + /// The file operations interface. + /// The file path for storing package information. + /// The filename for the report. private static void GetNotApprovedNpmPackages(List unknownPackages, ProjectResponse projectResponse, IFileOperations fileOperations, string filepath, string filename) { if (File.Exists(filename)) @@ -375,6 +502,15 @@ private static void GetNotApprovedNpmPackages(List unkn } WarningMessageForNoPackages(filename); } + + /// + /// Gets not approved NuGet packages and writes them to the report file. + /// + /// List of unknown NuGet packages. + /// The project response object. + /// The file operations interface. + /// The file path for storing package information. + /// The filename for the report. private static void GetNotApprovedNugetPackages(List unknownPackages, ProjectResponse projectResponse, IFileOperations fileOperations, string filepath, string filename) { if (File.Exists(filename)) @@ -407,6 +543,14 @@ private static void GetNotApprovedNugetPackages(List un WarningMessageForNoPackages(filename); } + /// + /// Gets not approved Cargo packages and writes them to the report file. + /// + /// List of unknown Cargo packages. + /// The project response object. + /// The file operations interface. + /// The file path for storing package information. + /// The filename for the report. private static void GetNotApprovedCargoPackages(List unknownPackages, ProjectResponse projectResponse, IFileOperations fileOperations, string filepath, string filename) { if (File.Exists(filename)) @@ -439,6 +583,14 @@ private static void GetNotApprovedCargoPackages(List un WarningMessageForNoPackages(filename); } + /// + /// Gets not approved Conan packages and writes them to the report file. + /// + /// List of unknown Conan packages. + /// The project response object. + /// The file operations interface. + /// The file path for storing package information. + /// The filename for the report. private static void GetNotApprovedConanPackages(List unknownPackages, ProjectResponse projectResponse, IFileOperations fileOperations, string filepath, string filename) { if (File.Exists(filename)) @@ -474,6 +626,15 @@ private static void GetNotApprovedConanPackages(List un WarningMessageForNoPackages(filename); } + + /// + /// Gets not approved Python packages and writes them to the report file. + /// + /// List of unknown Python packages. + /// The project response object. + /// The file operations interface. + /// The file path for storing package information. + /// The filename for the report. private static void GetNotApprovedPythonPackages(List unknownPackages, ProjectResponse projectResponse, IFileOperations fileOperations, string filepath, string filename) { if (File.Exists(filename)) @@ -508,6 +669,15 @@ private static void GetNotApprovedPythonPackages(List u } WarningMessageForNoPackages(filename); } + + /// + /// Gets not approved Debian packages and writes them to the report file. + /// + /// List of unknown Debian packages. + /// The project response object. + /// The file operations interface. + /// The file path for storing package information. + /// The filename for the report. public static void GetNotApprovedDebianPackages(List unknownPackages, ProjectResponse projectResponse, IFileOperations fileOperations, string filepath, string filename) { if (File.Exists(filename)) @@ -542,6 +712,15 @@ public static void GetNotApprovedDebianPackages(List un } WarningMessageForNoPackages(filename); } + + /// + /// Gets not approved Maven packages and writes them to the report file. + /// + /// List of unknown Maven packages. + /// The project response object. + /// The file operations interface. + /// The file path for storing package information. + /// The filename for the report. private static void GetNotApprovedMavenPackages(List unknownPackages, ProjectResponse projectResponse, IFileOperations fileOperations, string filepath, string filename) { if (File.Exists(filename)) @@ -576,6 +755,15 @@ private static void GetNotApprovedMavenPackages(List un } WarningMessageForNoPackages(filename); } + + /// + /// Gets not approved Chocolatey packages and writes them to the report file. + /// + /// List of unknown Chocolatey packages. + /// The project response object. + /// The file operations interface. + /// The file path for storing package information. + /// The filename for the report. public static void GetNotApprovedChocoPackages(List unknownPackages, ProjectResponse projectResponse, IFileOperations fileOperations, string filepath, string filename) { if (File.Exists(filename)) @@ -609,5 +797,6 @@ public static void GetNotApprovedChocoPackages(List unk WarningMessageForNoPackages(filename); } + #endregion } } diff --git a/src/ArtifactoryUploader/PackageUploader.cs b/src/ArtifactoryUploader/PackageUploader.cs index 65dc95a6c..8bf8d2ccc 100644 --- a/src/ArtifactoryUploader/PackageUploader.cs +++ b/src/ArtifactoryUploader/PackageUploader.cs @@ -26,10 +26,21 @@ namespace LCT.ArtifactoryUploader /// public static class PackageUploader { + #region Fields + static readonly ILog Logger = LoggerFactory.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); public static readonly UploaderKpiData uploaderKpiData = new UploaderKpiData(); private static readonly EnvironmentHelper environmentHelper = new EnvironmentHelper(); + #endregion + + #region Methods + + /// + /// Asynchronously uploads packages to Artifactory based on the application settings. + /// + /// The common application settings. + /// A task representing the asynchronous operation. public static async Task UploadPackageToArtifactory(CommonAppSettings appSettings) { Logger.Debug($"UploadPackageToArtifactory():Upload package to artifactory process has started"); @@ -85,5 +96,6 @@ public static async Task UploadPackageToArtifactory(CommonAppSettings appSetting } + #endregion } } diff --git a/src/ArtifactoryUploader/Program.cs b/src/ArtifactoryUploader/Program.cs index ca7dbfd92..53d0437b2 100644 --- a/src/ArtifactoryUploader/Program.cs +++ b/src/ArtifactoryUploader/Program.cs @@ -1,4 +1,4 @@ -// -------------------------------------------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------------------------------------------- // SPDX-FileCopyrightText: 2025 Siemens AG // // SPDX-License-Identifier: MIT @@ -9,7 +9,6 @@ using LCT.APICommunications; using LCT.APICommunications.Interfaces; using LCT.APICommunications.Model; -using LCT.ArtifactoryUploader; using LCT.Common; using LCT.Common.Constants; using LCT.Common.Logging; @@ -28,7 +27,7 @@ using System.Reflection; using System.Threading.Tasks; -namespace ArtifactoryUploader +namespace LCT.ArtifactoryUploader { [ExcludeFromCodeCoverage] public static class Program @@ -152,4 +151,4 @@ private static string GetBomFilePath(CommonAppSettings appSettings) return string.Empty; } } -} +} \ No newline at end of file diff --git a/src/ArtifactoryUploader/UploadToArtifactory.cs b/src/ArtifactoryUploader/UploadToArtifactory.cs index 05fbed133..26cc45df5 100644 --- a/src/ArtifactoryUploader/UploadToArtifactory.cs +++ b/src/ArtifactoryUploader/UploadToArtifactory.cs @@ -25,11 +25,30 @@ namespace LCT.ArtifactoryUploader { public static class UploadToArtifactory { + #region Fields + static readonly ILog Logger = LoggerFactory.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - public static IJFrogService JFrogService { get; set; } private static readonly Dictionary> repoCache = new(); private const string Choco = "CHOCO"; private const string Nuget = "NUGET"; + + #endregion + + #region Properties + + public static IJFrogService JFrogService { get; set; } + + #endregion + + #region Methods + + /// + /// Asynchronously retrieves the list of components to be uploaded to Artifactory. + /// + /// The list of components from the BOM data. + /// The common application settings. + /// The display information for packages. + /// A list of components prepared for upload to Artifactory. public async static Task> GetComponentsToBeUploadedToArtifactory(List comparisonBomData, CommonAppSettings appSettings, DisplayPackagesInfo displayPackagesInfo) @@ -158,6 +177,12 @@ private static string GetComponentType(Component item) } return string.Empty; } + + /// + /// Gets the JFrog repository path for the specified component. + /// + /// The component to generate the path for. + /// The JFrog repository path. public static string GetJfrogRepPath(ComponentsToArtifactory component) { string jfrogRepPath = string.Empty; @@ -195,6 +220,13 @@ public static string GetJfrogRepPath(ComponentsToArtifactory component) } return jfrogRepPath; } + + /// + /// Gets the destination repository name based on the component and application settings. + /// + /// The component to evaluate. + /// The common application settings. + /// The destination repository name. private static string GetDestinationRepo(Component item, CommonAppSettings appSettings) { var packageType = GetPackageType(item); @@ -225,6 +257,13 @@ private static string GetDestinationRepo(Component item, CommonAppSettings appSe return string.Empty; } + /// + /// Gets the package path for the specified component. + /// + /// The component to generate the path for. + /// The AQL query result. + /// The source component. + /// The package path. private static string GetPackagePath(ComponentsToArtifactory component, AqlResult aqlResult, Component item) { switch (component.ComponentType) @@ -264,6 +303,12 @@ private static string GetPackagePath(ComponentsToArtifactory component, AqlResul return string.Empty; } } + + /// + /// Gets the copy API URL for copying the component to the destination repository. + /// + /// The component to generate the URL for. + /// The copy API URL. public static string GetCopyURL(ComponentsToArtifactory component) { string url = string.Empty; @@ -313,6 +358,11 @@ public static string GetCopyURL(ComponentsToArtifactory component) return component.DryRun ? $"{url}&dry=1" : url; } + /// + /// Gets the move API URL for moving the component to the destination repository. + /// + /// The component to generate the URL for. + /// The move API URL. public static string GetMoveURL(ComponentsToArtifactory component) { string url = string.Empty; @@ -362,6 +412,11 @@ public static string GetMoveURL(ComponentsToArtifactory component) return component.DryRun ? $"{url}&dry=1" : url; } + /// + /// Gets the JFrog package name for the specified component. + /// + /// The component to generate the package name for. + /// The JFrog package name. private static string GetJfrogPackageName(ComponentsToArtifactory component) { return component.ComponentType switch @@ -376,6 +431,12 @@ private static string GetJfrogPackageName(ComponentsToArtifactory component) }; } + /// + /// Asynchronously adds unknown packages to the display packages information. + /// + /// The component to add as an unknown package. + /// The display information for packages. + /// A task representing the asynchronous operation. private static async Task AddUnknownPackagesAsync(Component item, DisplayPackagesInfo displayPackagesInfo) { string GetPropertyValue(string propertyName) => @@ -389,7 +450,12 @@ string GetPropertyValue(string propertyName) => AddUnknownComponentToDisplayList(projectType, components, displayPackagesInfo); } - // Helper to reduce code duplication for adding unknown components to display lists + /// + /// Adds an unknown component to the appropriate display list based on project type. + /// + /// The type of the project. + /// The component to add. + /// The display information for packages. private static void AddUnknownComponentToDisplayList(string projectType, ComponentsToArtifactory component, DisplayPackagesInfo displayPackagesInfo) { switch (projectType) @@ -421,6 +487,11 @@ private static void AddUnknownComponentToDisplayList(string projectType, Compone } } + /// + /// Gets the unknown package information from a component. + /// + /// The component to extract information from. + /// A task containing the unknown package information. private static Task GetUnknownPackageinfo(Component item) { @@ -433,6 +504,14 @@ private static Task GetUnknownPackageinfo(Component ite } + /// + /// Gets the repository name based on the package type. + /// + /// The type of the package. + /// The internal repository name. + /// The development repository name. + /// The cleared third-party repository name. + /// The repository name corresponding to the package type. private static string GetRepoName(PackageType packageType, string internalRepo, string developmentRepo, string clearedThirdPartyRepo) { switch (packageType) @@ -447,6 +526,12 @@ private static string GetRepoName(PackageType packageType, string internalRepo, return string.Empty; } } + + /// + /// Asynchronously gets the source repository details for a component. + /// + /// The component to retrieve repository details for. + /// The AQL result containing repository details, or null if not found. public async static Task GetSrcRepoDetailsForComponent(Component item) { if (item.Purl.Contains("pypi", StringComparison.OrdinalIgnoreCase)) @@ -489,6 +574,13 @@ public async static Task GetSrcRepoDetailsForComponent(Component item return null; } + /// + /// Asynchronously gets the list of components from repositories based on package type. + /// + /// The list of repository names. + /// The JFrog service instance. + /// The type of package (npm or cargo). + /// A list of AQL results for the specified package type. public static async Task> GetPackageTypeBased_ListOfComponentsFromRepo(string[] repoList, IJFrogService jFrogService, string packageType) { var aqlResultList = new List(); @@ -520,6 +612,12 @@ public static async Task> GetPackageTypeBased_ListOfComponentsFr return aqlResultList; } + /// + /// Asynchronously gets the list of internal components from repositories. + /// + /// The list of repository names. + /// The JFrog service instance. + /// A list of AQL results for internal components. public static async Task> GetListOfComponentsFromRepo(string[] repoList, IJFrogService jFrogService) { var aqlResultList = new List(); @@ -542,6 +640,12 @@ public static async Task> GetListOfComponentsFromRepo(string[] r return aqlResultList; } + /// + /// Gets the Artifactory repository name by matching component properties. + /// + /// The list of AQL results to search. + /// The component to find. + /// The matching AQL result, or an empty result if not found. private static AqlResult GetArtifactoryRepoName(List aqlResultList, Component component) { string jfrogpackageName = GetFullNameOfComponent(component); @@ -566,6 +670,11 @@ private static AqlResult GetArtifactoryRepoName(List aqlResultList, C return new AqlResult(); } + /// + /// Gets the full name of a component, including group if present. + /// + /// The component to get the full name for. + /// The full component name. private static string GetFullNameOfComponent(Component item) { if (!string.IsNullOrEmpty(item.Group)) @@ -578,6 +687,12 @@ private static string GetFullNameOfComponent(Component item) } } + /// + /// Gets the Artifactory repository name for Conan packages. + /// + /// The list of AQL results to search. + /// The component to find. + /// The matching AQL result, or null if not found. private static AqlResult GetArtifactoryRepoNameForConan(List aqlResultList, Component component) { string jfrogcomponentPath = $"{component.Name}/{component.Version}"; @@ -588,6 +703,12 @@ private static AqlResult GetArtifactoryRepoNameForConan(List aqlResul return repoName; } + /// + /// Asynchronously gets the list of PyPI components from repositories. + /// + /// The list of repository names. + /// The JFrog service instance. + /// A list of AQL results for PyPI components. public static async Task> GetPypiListOfComponentsFromRepo(string[] repoList, IJFrogService jFrogService) { var aqlResultList = new List(); @@ -610,6 +731,12 @@ public static async Task> GetPypiListOfComponentsFromRepo(string } return aqlResultList; } + + /// + /// Gets the package type from the component's properties. + /// + /// The component to evaluate. + /// The package type. private static PackageType GetPackageType(Component item) { string GetPropertyValue(string propertyName) => @@ -637,5 +764,6 @@ string GetPropertyValue(string propertyName) => return PackageType.Unknown; } + #endregion } } diff --git a/src/LCT.APICommunications/ApiConstant.cs b/src/LCT.APICommunications/ApiConstant.cs index 38ddec4da..04aa7efec 100644 --- a/src/LCT.APICommunications/ApiConstant.cs +++ b/src/LCT.APICommunications/ApiConstant.cs @@ -9,73 +9,328 @@ namespace LCT.APICommunications { /// - /// constans need for all the api calls + /// Provides constant values used for API calls across the application. /// [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public static class ApiConstant { + #region Fields + + /// + /// The API suffix for SW360 component endpoints. + /// public const string Sw360ComponentApiSuffix = "/resource/api/components"; + + /// + /// The API suffix for SW360 release endpoints. + /// public const string Sw360ReleaseApiSuffix = "/resource/api/releases"; + + /// + /// The API suffix for SW360 projects endpoints. + /// public const string Sw360ProjectsApiSuffix = "/resource/api/projects"; + + /// + /// The API suffix for SW360 users endpoints. + /// public const string Sw360UsersSuffix = "/resource/api/users"; + + /// + /// The API suffix for SW360 resource endpoints. + /// public const string Sw360ResourceApiSuffix = "/resource/"; + + /// + /// The API suffix for SW360 project URL endpoints. + /// public const string Sw360ProjectUrlApiSuffix = "/group/guest/projects/-/project/detail/"; + + /// + /// The API suffix for SW360 release URL endpoints. + /// public const string Sw360ReleaseUrlApiSuffix = "/group/guest/components/-/component/release/detailRelease/"; + + /// + /// The API endpoint for searching SW360 releases by external ID. + /// public const string Sw360ReleaseByExternalId = "/resource/api/releases/searchByExternalIds"; + + /// + /// The API endpoint for searching SW360 components by external ID. + /// public const string Sw360ComponentByExternalId = "/resource/api/components/searchByExternalIds"; + + /// + /// The API prefix for triggering Fossology process. + /// public const string FossTriggerAPIPrefix = "/triggerFossologyProcess?uploadDescription="; + + /// + /// The API suffix for Fossology trigger with outdated flag. + /// public const string FossTriggerAPISuffix = "&markFossologyProcessOutdated=false"; + + /// + /// The MIME type for JSON content. + /// public const string ApplicationJson = "application/json"; + + /// + /// The MIME type for all application content types. + /// public const string ApplicationAllType = "application/*"; + + /// + /// The query parameter key for report format. + /// public const string ReportFormat = "reportFormat"; + + /// + /// The URL query parameter for component name searches. + /// public const string ComponentNameUrl = "?name="; + + /// + /// The external ID prefix for NPM packages. + /// public const string NPMExternalID = "pkg:npm/"; + + /// + /// The external ID prefix for NuGet packages. + /// public const string NugetExternalID = "pkg:nuget/"; + + /// + /// The external ID prefix for Conan packages. + /// public const string ConanExternalID = "pkg:conan/"; + + /// + /// The file extension for NPM packages. + /// public const string NpmExtension = ".tgz"; + + /// + /// The file extension for NuGet packages. + /// public const string NugetExtension = ".nupkg"; + + /// + /// The file extension for Debian packages. + /// public const string DebianExtension = ".debian"; + + /// + /// The file extension for Maven source packages. + /// public const string MavenExtension = "-sources.jar"; + + /// + /// The file extension for Python wheel packages. + /// public const string PythonExtension = ".whl"; + + /// + /// The file extension for Cargo crate packages. + /// public const string CargoExtension = ".crate"; + + /// + /// The API path for package storage information. + /// public const string PackageInfoApi = "/api/storage/"; + + /// + /// The API path for copying packages. + /// public const string CopyPackageApi = "/api/copy/"; + + /// + /// The API path for moving packages. + /// public const string MovePackageApi = "/api/move/"; + + /// + /// The releases endpoint path segment. + /// public const string Releases = "releases"; + + /// + /// The release endpoint path segment. + /// public const string Release = "release"; + + /// + /// The query parameter key for folder ID. + /// public const string FolderId = "folderId"; + + /// + /// The query parameter key for upload ID. + /// public const string UploadId = "uploadId"; + + /// + /// The include filter keyword. + /// public const string Include = "Include"; + + /// + /// The exclude filter keyword. + /// public const string Exclude = "Exclude"; + + /// + /// The HTTP Accept header name. + /// public const string Accept = "Accept"; + + /// + /// The attachment type for source files. + /// public const string SOURCE = "SOURCE"; + + /// + /// The email field identifier. + /// public const string Email = "Email"; + + /// + /// The OSS (Open Source Software) identifier. + /// public const string Oss = "OSS"; + + /// + /// The HTTP POST method name. + /// public const string POST = "POST"; + + /// + /// The public visibility identifier. + /// public const string Public = "public"; + + /// + /// The Package URL identifier key. + /// public const string PurlId = "package-url"; + + /// + /// The form field name for file input. + /// public const string FileInput = "fileInput"; + + /// + /// The attachments endpoint path segment. + /// public const string Attachments = "attachments"; + + /// + /// The HTTP Authorization header name. + /// public const string Authorization = "Authorization"; + + /// + /// The JFrog API authentication header name. + /// public const string JFrog_API_Header = "X-JFrog-Art-Api"; + + /// + /// The upload description parameter key. + /// public const string UploadDescription = "uploadDescription"; + + /// + /// The additional data key for Fossology URL. + /// public const string AdditionalDataFossologyURL = "fossology url"; + + /// + /// The default filename for attachment JSON files. + /// public const string AttachmentJsonFileName = "Attachment.json"; + + /// + /// The API suffix for Fossology folders endpoint. + /// public const string FossFoldersApiSuffix = "/repo/api/v1/folders"; + + /// + /// The API suffix for Fossology groups endpoint. + /// public const string FossGroupsApiSuffix = "/repo/api/v1/groups"; + + /// + /// The API suffix for Fossology uploads endpoint. + /// public const string FossUploadsApiSuffix = "/repo/api/v1/uploads"; + + /// + /// The API suffix for Fossology jobs endpoint. + /// public const string FossJobsApiSuffix = "/repo/api/v1/jobs"; + + /// + /// The API suffix for Fossology report endpoint. + /// public const string FossReportApiSuffix = "/repo/api/v1/report"; + + /// + /// The API suffix for Fossology users endpoint. + /// public const string FossUsersApiSuffix = "/repo/api/v1/users"; + + /// + /// The URL suffix for Fossology upload job view. + /// public const string FossUploadJobUrlSuffix = "/repo/?mod=view-license&upload="; + + /// + /// The API suffix for searching SW360 releases by name. + /// public const string Sw360ReleaseNameApiSuffix = "/resource/api/releases?name="; + + /// + /// The API suffix for searching SW360 components by name. + /// public const string Sw360ComponentNameApiSuffix = "/resource/api/components?name="; + + /// + /// The API suffix for searching SW360 projects by tag with active state. + /// public const string Sw360ProjectByTagApiSuffix = "/resource/api/projects?allDetails=true&_sw360_portlet_projects_STATE=ACTIVE&tag="; + + /// + /// The error message for upload failures. + /// public const string ErrorInUpload = "Error In Upload"; + + /// + /// The error message for invalid Artifactory configuration. + /// public const string InvalidArtifactory = "Invalid artifactory"; + + /// + /// The error message when a package is not found. + /// public const string PackageNotFound = "Package Not Found"; + + /// + /// The configuration key for Artifactory repository name. + /// public const string ArtifactoryRepoName = "ArtifactoryRepoName"; + + /// + /// The API endpoint for JFrog Artifactory AQL search. + /// public const string JfrogArtifactoryApiSearchAql = $"/api/search/aql"; + + /// + /// The list of retry intervals in seconds for API calls. + /// public static readonly List APIRetryIntervals = [5, 10, 30]; // in seconds + + #endregion Fields } } diff --git a/src/LCT.APICommunications/AttachmentHelper.cs b/src/LCT.APICommunications/AttachmentHelper.cs index 81101c35b..18314d8c6 100644 --- a/src/LCT.APICommunications/AttachmentHelper.cs +++ b/src/LCT.APICommunications/AttachmentHelper.cs @@ -1,4 +1,4 @@ -// -------------------------------------------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------------------------------------------- // SPDX-FileCopyrightText: 2025 Siemens AG // // SPDX-License-Identifier: MIT @@ -24,16 +24,63 @@ namespace LCT.APICommunications /// public class AttachmentHelper { + #region Fields + + /// + /// The logger instance for logging messages and errors. + /// static readonly ILog Logger = LoggerFactory.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// The full path to the attachment JSON file. + /// private readonly string fullPathOfAttachmentJSON = $"{Path.GetTempPath()}/ClearingTool/DownloadedFiles/Attachment.json"; + + /// + /// The SW360 authentication token. + /// private readonly string sw360AuthToken; + + /// + /// The SW360 authentication token type. + /// private readonly string sw360AuthTokenType; + + /// + /// The SW360 release API endpoint URL. + /// private readonly string sw360ReleaseApi; + + /// + /// Lock object for thread-safe access to the attachments JSON file. + /// private readonly object attachmentsJSONFileLock = new object(); + /// + /// The MIME type for compressed files. + /// private const string fileMimeType = "application /x-compressed"; + + /// + /// The form key used for file uploads. + /// private const string fileFormKey = "file"; + + /// + /// Error message for attachment failures. + /// private const string AttachmentErrorMessage = "Not able to attachment"; + + #endregion Fields + + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + /// The SW360 authentication token type. + /// The SW360 authentication token. + /// The SW360 release API endpoint URL. public AttachmentHelper(string sw360TokenType, string sw360Token, string releaseApi) { sw360AuthToken = sw360Token; @@ -41,13 +88,16 @@ public AttachmentHelper(string sw360TokenType, string sw360Token, string release sw360ReleaseApi = releaseApi; } + #endregion Constructors + + #region Methods + /// - /// Attaches the component Source to Sw360 + /// Attaches the component source to SW360 by uploading the attachment file. /// - /// releaseId - /// attachmentType - /// attachmentFile - /// attached api url + /// The attachment report containing release and file information. + /// The comparison BOM data for the component. + /// The release attachment API URL. public string AttachComponentSourceToSW360(AttachReport attachReport, ComparisonBomData comparisonBomData) { Uri url = new Uri($"{sw360ReleaseApi}/{attachReport.ReleaseId}/{ApiConstant.Attachments}"); @@ -129,8 +179,11 @@ public string AttachComponentSourceToSW360(AttachReport attachReport, Comparison /// - /// WriteAttachmentsJSONFile + /// Writes the attachments JSON file to the specified folder path. /// + /// The name of the attachment file. + /// The folder path where the JSON file will be written. + /// The attachment report containing attachment details. public static void WriteAttachmentsJSONFile(string fileName, string folderPath, AttachReport attachReport) { AttachmentJson attachment = new AttachmentJson @@ -158,10 +211,20 @@ public static void WriteAttachmentsJSONFile(string fileName, string folderPath, file.Close(); } + /// + /// Creates a unique form data boundary string for multipart requests. + /// + /// A unique boundary string based on the current timestamp. private static string CreateFormDataBoundary() { return "---------------------------" + DateTime.Now.Ticks.ToString("x"); } + + /// + /// Handles the HTTP accepted status response and logs appropriate messages. + /// + /// The HTTP web response to check. + /// The comparison BOM data containing component information. private static void HandleAcceptedStatus(HttpWebResponse httpResponse, ComparisonBomData component) { if (httpResponse.StatusCode == HttpStatusCode.Accepted) @@ -173,7 +236,7 @@ private static void HandleAcceptedStatus(HttpWebResponse httpResponse, Compariso Logger.Debug($"HTTP Status Code: {httpResponse.StatusCode}"); } } - } -} - + #endregion Methods + } +} \ No newline at end of file diff --git a/src/LCT.APICommunications/DebianJfrogAPICommunication.cs b/src/LCT.APICommunications/DebianJfrogAPICommunication.cs index fc77d8d63..1f62b0e52 100644 --- a/src/LCT.APICommunications/DebianJfrogAPICommunication.cs +++ b/src/LCT.APICommunications/DebianJfrogAPICommunication.cs @@ -1,4 +1,4 @@ -// -------------------------------------------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------------------------------------------- // SPDX-FileCopyrightText: 2025 Siemens AG // // SPDX-License-Identifier: MIT @@ -15,18 +15,57 @@ namespace LCT.APICommunications { + /// + /// Provides Debian-specific JFrog Artifactory API communication operations. + /// public class DebianJfrogAPICommunication : JfrogApicommunication { + #region Fields - + /// + /// Logger instance for this class. + /// static readonly ILog Logger = LoggerFactory.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// Environment helper instance for exit handling. + /// private static readonly EnvironmentHelper environmentHelper = new EnvironmentHelper(); + + #endregion + + #region Properties + + /// + /// Gets or sets the timeout in seconds for HTTP requests. + /// private static int TimeoutInSec { get; set; } + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + /// The repository domain name. + /// The source repository name. + /// The repository credentials. + /// The timeout in seconds. public DebianJfrogAPICommunication(string repoDomainName, string srcrepoName, ArtifactoryCredentials repoCredentials, int timeout) : base(repoDomainName, srcrepoName, repoCredentials, timeout) { TimeoutInSec = timeout; } + #endregion + + #region Methods + + /// + /// Creates and configures an HTTP client with authentication. + /// + /// The artifactory credentials. + /// A configured HTTP client instance. private static HttpClient GetHttpClient(ArtifactoryCredentials credentials) { var handler = new RetryHttpClientHandler() @@ -40,6 +79,10 @@ private static HttpClient GetHttpClient(ArtifactoryCredentials credentials) return httpClient; } + /// + /// Asynchronously retrieves the API key from Artifactory. + /// + /// An HTTP response message containing the API key. public override async Task GetApiKey() { HttpClient httpClient = GetHttpClient(ArtifactoryCredentials); @@ -47,6 +90,11 @@ public override async Task GetApiKey() return await httpClient.GetAsync(url); } + /// + /// Asynchronously copies a component from a remote repository. + /// + /// The component to copy. + /// An HTTP response message indicating the result of the copy operation. public override async Task CopyFromRemoteRepo(ComponentsToArtifactory component) { HttpClient httpClient = GetHttpClient(ArtifactoryCredentials); @@ -54,6 +102,11 @@ public override async Task CopyFromRemoteRepo(ComponentsToA return await httpClient.PostAsync(component.CopyPackageApiUrl, httpContent); } + /// + /// Asynchronously moves a component from one repository to another. + /// + /// The component to move. + /// An HTTP response message indicating the result of the move operation. public override async Task MoveFromRepo(ComponentsToArtifactory component) { HttpClient httpClient = GetHttpClient(ArtifactoryCredentials); @@ -61,6 +114,11 @@ public override async Task MoveFromRepo(ComponentsToArtifac return await httpClient.PostAsync(component.MovePackageApiUrl, httpContent); } + /// + /// Asynchronously retrieves package information from Artifactory. + /// + /// The component to retrieve information for. + /// An HTTP response message containing the package information. public override async Task GetPackageInfo(ComponentsToArtifactory component) { HttpResponseMessage responseMessage = new HttpResponseMessage(); @@ -80,6 +138,12 @@ public override async Task GetPackageInfo(ComponentsToArtif return result; } + /// + /// Updates the package properties in JFrog Artifactory with the SW360 release URL. + /// + /// The SW360 release URL. + /// The destination repository name. + /// The upload arguments containing package information. public override void UpdatePackagePropertiesInJfrog(string sw360releaseUrl, string destRepoName, UploadArgs uploadArgs) { HttpClient httpClient = GetHttpClient(ArtifactoryCredentials); @@ -88,8 +152,7 @@ public override void UpdatePackagePropertiesInJfrog(string sw360releaseUrl, stri $"properties=sw360url={sw360releaseUrl}"; httpClient.PutAsync(url, httpContent); } - } -} - - + #endregion + } +} \ No newline at end of file diff --git a/src/LCT.APICommunications/FileInfoExtensions.cs b/src/LCT.APICommunications/FileInfoExtensions.cs index 94266831c..f7218a73f 100644 --- a/src/LCT.APICommunications/FileInfoExtensions.cs +++ b/src/LCT.APICommunications/FileInfoExtensions.cs @@ -15,9 +15,28 @@ namespace LCT.APICommunications /// public static class FileInfoExtensions { + #region Fields + + /// + /// The template string for multipart form data headers. + /// public const string HeaderTemplate = "--{0}\r\nContent-Disposition: form-data; name=\"{1}\"; filename=\"{2}\"\r\nContent-Type: {3}\r\n\r\n"; + #endregion Fields + + #region Methods + /// + /// Writes the file content as multipart form data to the specified stream. + /// + /// The file to write to the stream. + /// The destination stream to write the multipart form data to. + /// The MIME boundary string used to separate form data parts. + /// The MIME type of the file content. + /// The form field key name for the file. + /// Thrown when file or stream is null. + /// Thrown when mimeBoundary, mimeType, or formKey is empty. + /// Thrown when the specified file does not exist. public static void WriteMultipartFormData( this FileInfo file, Stream stream, @@ -63,6 +82,11 @@ public static void WriteMultipartFormData( stream.Write(newlineBytes, 0, newlineBytes.Length); } + /// + /// Checks if the specified file exists and throws an exception if it does not. + /// + /// The file to check for existence. + /// Thrown when the specified file does not exist. private static void CheckIfFileExists(FileInfo file) { if (!file.Exists) @@ -70,5 +94,7 @@ private static void CheckIfFileExists(FileInfo file) throw new FileNotFoundException("Unable to find file to write to stream.", file.FullName); } } + + #endregion Methods } } diff --git a/src/LCT.APICommunications/Interfaces/IJFrogApiCommunication.cs b/src/LCT.APICommunications/Interfaces/IJFrogApiCommunication.cs index ee226ee5a..102cd9d64 100644 --- a/src/LCT.APICommunications/Interfaces/IJFrogApiCommunication.cs +++ b/src/LCT.APICommunications/Interfaces/IJFrogApiCommunication.cs @@ -10,18 +10,52 @@ namespace LCT.APICommunications.Interfaces { + /// + /// Defines the contract for JFrog Artifactory API communication operations. + /// public interface IJFrogApiCommunication { + /// + /// Asynchronously retrieves package information from the Artifactory repository. + /// + /// The component containing the package information request details. + /// An HttpResponseMessage containing the package information. Task GetPackageInfo(ComponentsToArtifactory component); + /// + /// Asynchronously deletes a package from the JFrog repository. + /// + /// The name of the repository containing the package. + /// The name of the component to delete. + /// An HttpResponseMessage indicating the result of the delete operation. Task DeletePackageFromJFrogRepo(string repoName, string componentName); + /// + /// Asynchronously copies a package from a remote repository to the local repository. + /// + /// The component containing the copy operation details. + /// An HttpResponseMessage indicating the result of the copy operation. Task CopyFromRemoteRepo(ComponentsToArtifactory component); + /// + /// Asynchronously moves a package from one repository to another. + /// + /// The component containing the move operation details. + /// An HttpResponseMessage indicating the result of the move operation. Task MoveFromRepo(ComponentsToArtifactory component); + /// + /// Asynchronously retrieves the API key from the Artifactory server. + /// + /// An HttpResponseMessage containing the API key response. Task GetApiKey(); + /// + /// Updates package properties in JFrog Artifactory with SW360 release URL information. + /// + /// The SW360 release URL to associate with the package. + /// The destination repository name. + /// The upload arguments containing package details. void UpdatePackagePropertiesInJfrog(string sw360releaseUrl, string destRepoName, UploadArgs uploadArgs); } } diff --git a/src/LCT.APICommunications/Interfaces/IJfrogAqlApiCommunication.cs b/src/LCT.APICommunications/Interfaces/IJfrogAqlApiCommunication.cs index 7542cbb38..2ade29a11 100644 --- a/src/LCT.APICommunications/Interfaces/IJfrogAqlApiCommunication.cs +++ b/src/LCT.APICommunications/Interfaces/IJfrogAqlApiCommunication.cs @@ -11,49 +11,49 @@ namespace LCT.APICommunications.Interfaces { /// - /// The IJfrogAqlApiCommunication interface + /// Defines the contract for JFrog AQL (Artifactory Query Language) API communication. /// public interface IJfrogAqlApiCommunication { /// - /// Gets the internal component data based on repo name + /// Asynchronously gets the internal component data based on repository name. /// - /// repoName - /// HttpResponseMessage + /// The repository name. + /// A task containing the HTTP response message. Task GetInternalComponentDataByRepo(string repoName); + /// - /// Gets the internal component data based on repo name + /// Asynchronously gets the NPM component data based on repository name. /// - /// repoName - /// HttpResponseMessage + /// The repository name. + /// A task containing the HTTP response message. Task GetNpmComponentDataByRepo(string repoName); + /// - /// Gets the internal component data based on repo name + /// Asynchronously gets the PyPI component data based on repository name. /// - /// repoName - /// HttpResponseMessage + /// The repository name. + /// A task containing the HTTP response message. Task GetPypiComponentDataByRepo(string repoName); + /// - /// Gets the internal component data based on repo name + /// Asynchronously gets the Cargo component data based on repository name. /// - /// repoName - /// HttpResponseMessage + /// The repository name. + /// A task containing the HTTP response message. Task GetCargoComponentDataByRepo(string repoName); - /// - /// Gets the package information in the repo, via the name or path + /// Asynchronously gets the package information in the repository. /// - /// repoName - /// repoName - /// repoName - /// AqlResult + /// The component to query in Artifactory. + /// A task containing the HTTP response message. Task GetPackageInfo(ComponentsToArtifactory component = null); /// - /// Checks connectivity with JFrog server + /// Asynchronously checks connectivity with the JFrog server. /// - /// HttpResponseMessage + /// A task containing the HTTP response message. Task CheckConnection(); } } diff --git a/src/LCT.APICommunications/Interfaces/ISW360APICommunication.cs b/src/LCT.APICommunications/Interfaces/ISW360APICommunication.cs index 7be11097b..53eb683eb 100644 --- a/src/LCT.APICommunications/Interfaces/ISW360APICommunication.cs +++ b/src/LCT.APICommunications/Interfaces/ISW360APICommunication.cs @@ -43,4 +43,4 @@ public interface ISw360ApiCommunication Task GetComponentDetailsByUrl(string componentLink); Task GetAllReleasesWithAllData(int page, int pageEntries); } -} +} \ No newline at end of file diff --git a/src/LCT.APICommunications/JfrogApicommunication.cs b/src/LCT.APICommunications/JfrogApicommunication.cs index 6e910fa56..95734874e 100644 --- a/src/LCT.APICommunications/JfrogApicommunication.cs +++ b/src/LCT.APICommunications/JfrogApicommunication.cs @@ -13,15 +13,44 @@ namespace LCT.APICommunications { + /// + /// Abstract base class for JFrog Artifactory API communication operations. + /// public abstract class JfrogApicommunication : IJFrogApiCommunication { + #region Properties + + /// + /// Gets or sets the domain name of the JFrog Artifactory server. + /// protected string DomainName { get; set; } + /// + /// Gets or sets the credentials for accessing the Artifactory repository. + /// protected ArtifactoryCredentials ArtifactoryCredentials { get; set; } + /// + /// Gets or sets the source repository name. + /// protected string SourceRepoName { get; set; } + + /// + /// Gets or sets the timeout value in seconds for HTTP requests. + /// private static int TimeoutInSec { get; set; } + #endregion Properties + + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + /// The domain name of the repository. + /// The source repository name. + /// The credentials for accessing the Artifactory repository. + /// The timeout value in seconds for HTTP requests. protected JfrogApicommunication(string repoDomainName, string srcrepoName, ArtifactoryCredentials artifactoryCredentials, int timeout) { DomainName = repoDomainName; @@ -30,6 +59,15 @@ protected JfrogApicommunication(string repoDomainName, string srcrepoName, Artif TimeoutInSec = timeout; } + #endregion Constructors + + #region Methods + + /// + /// Creates and configures an HttpClient instance with authentication and timeout settings. + /// + /// The Artifactory credentials for authentication. + /// A configured HttpClient instance. private static HttpClient GetHttpClient(ArtifactoryCredentials credentials) { var handler = new RetryHttpClientHandler() @@ -43,6 +81,12 @@ private static HttpClient GetHttpClient(ArtifactoryCredentials credentials) return httpClient; } + /// + /// Asynchronously deletes a package from the JFrog repository. + /// + /// The name of the repository containing the package. + /// The name of the component to delete. + /// An HttpResponseMessage indicating the result of the delete operation. public async Task DeletePackageFromJFrogRepo(string repoName, string componentName) { HttpClient httpClient = GetHttpClient(ArtifactoryCredentials); @@ -51,15 +95,41 @@ public async Task DeletePackageFromJFrogRepo(string repoNam return await httpClient.DeleteAsync(url); } + /// + /// Asynchronously retrieves the API key from the Artifactory server. + /// + /// An HttpResponseMessage containing the API key response. public abstract Task GetApiKey(); + /// + /// Asynchronously retrieves package information from the Artifactory repository. + /// + /// The component containing the package information request details. + /// An HttpResponseMessage containing the package information. public abstract Task GetPackageInfo(ComponentsToArtifactory component); + /// + /// Asynchronously copies a package from a remote repository to the local repository. + /// + /// The component containing the copy operation details. + /// An HttpResponseMessage indicating the result of the copy operation. public abstract Task CopyFromRemoteRepo(ComponentsToArtifactory component); + /// + /// Asynchronously moves a package from one repository to another. + /// + /// The component containing the move operation details. + /// An HttpResponseMessage indicating the result of the move operation. public abstract Task MoveFromRepo(ComponentsToArtifactory component); + /// + /// Updates package properties in JFrog Artifactory with SW360 release URL information. + /// + /// The SW360 release URL to associate with the package. + /// The destination repository name. + /// The upload arguments containing package details. public abstract void UpdatePackagePropertiesInJfrog(string sw360releaseUrl, string destRepoName, UploadArgs uploadArgs); + #endregion Methods } } diff --git a/src/LCT.APICommunications/JfrogAqlApiCommunication.cs b/src/LCT.APICommunications/JfrogAqlApiCommunication.cs index a9364d540..b96ee5b76 100644 --- a/src/LCT.APICommunications/JfrogAqlApiCommunication.cs +++ b/src/LCT.APICommunications/JfrogAqlApiCommunication.cs @@ -20,16 +20,33 @@ namespace LCT.APICommunications /// public class JfrogAqlApiCommunication : IJfrogAqlApiCommunication { + #region Properties + + /// + /// Gets or sets the domain name of the JFrog Artifactory server. + /// protected string DomainName { get; set; } + + /// + /// Gets or sets the timeout value in seconds for HTTP requests. + /// private static int TimeoutInSec { get; set; } + + /// + /// Gets or sets the credentials for accessing the Artifactory repository. + /// protected ArtifactoryCredentials ArtifactoryCredentials { get; set; } + #endregion Properties + + #region Constructors + /// - /// The JfrogAqlApiCommunication constructor + /// Initializes a new instance of the class. /// - /// repoDomainName - /// artifactoryCredentials - /// timeout + /// The domain name of the repository. + /// The credentials for accessing the Artifactory repository. + /// The timeout value in seconds for HTTP requests. public JfrogAqlApiCommunication(string repoDomainName, ArtifactoryCredentials artifactoryCredentials, int timeout) { DomainName = repoDomainName; @@ -37,6 +54,14 @@ public JfrogAqlApiCommunication(string repoDomainName, ArtifactoryCredentials ar TimeoutInSec = timeout; } + #endregion Constructors + + #region Methods + + /// + /// Asynchronously checks the connection to the Artifactory server. + /// + /// An HttpResponseMessage indicating the connection status. public async Task CheckConnection() { HttpClient httpClient = GetHttpClient(ArtifactoryCredentials); @@ -45,6 +70,12 @@ public async Task CheckConnection() return await httpClient.GetAsync(url); } + /// + /// Asynchronously retrieves component data from a specified repository using AQL. + /// + /// The name of the repository to query. + /// The fields to include in the AQL query result. + /// An HttpResponseMessage containing the component data. private async Task GetComponentDataByRepo(string repoName, string includeFields) { string aqlQueryToBody = BuildSimpleAqlQuery(repoName, includeFields); @@ -57,6 +88,12 @@ private async Task GetComponentDataByRepo(string repoName, return await httpClient.PostAsync(uri, httpContent); } + /// + /// Builds a simple AQL query string for a repository with specified include fields. + /// + /// The name of the repository to query. + /// The fields to include in the query result. + /// A formatted AQL query string. private static string BuildSimpleAqlQuery(string repoName, string includeFields) { // Helper to build simple AQL queries for repo and include fields @@ -64,31 +101,50 @@ private static string BuildSimpleAqlQuery(string repoName, string includeFields) } /// - /// Gets the Internal Component Data By Repo name + /// Asynchronously retrieves internal component data from a specified repository. /// - /// - /// + /// The name of the repository to query. + /// An HttpResponseMessage containing the internal component data. public async Task GetInternalComponentDataByRepo(string repoName) { return await GetComponentDataByRepo(repoName, "\"repo\", \"path\", \"name\", \"actual_sha1\",\"actual_md5\",\"sha256\""); } + + /// + /// Asynchronously retrieves NPM component data from a specified repository. + /// + /// The name of the repository to query. + /// An HttpResponseMessage containing the NPM component data. public async Task GetNpmComponentDataByRepo(string repoName) { return await GetComponentDataByRepo(repoName, "\"repo\", \"path\", \"name\",\"@npm.name\",\"@npm.version\", \"actual_sha1\",\"actual_md5\",\"sha256\""); } + + /// + /// Asynchronously retrieves PyPI component data from a specified repository. + /// + /// The name of the repository to query. + /// An HttpResponseMessage containing the PyPI component data. public async Task GetPypiComponentDataByRepo(string repoName) { return await GetComponentDataByRepo(repoName, "\"repo\", \"path\", \"name\",\"@pypi.normalized.name\",\"@pypi.version\", \"actual_sha1\",\"actual_md5\",\"sha256\""); } + + /// + /// Asynchronously retrieves Cargo component data from a specified repository. + /// + /// The name of the repository to query. + /// An HttpResponseMessage containing the Cargo component data. public async Task GetCargoComponentDataByRepo(string repoName) { return await GetComponentDataByRepo(repoName, "\"repo\", \"path\", \"name\",\"@crate.name\",\"@crate.version\", \"actual_sha1\",\"actual_md5\",\"sha256\""); } /// - /// Gets the package information in the repo, via the name or path + /// Asynchronously retrieves package information from the repository via name or path. /// - + /// The component containing package name and path information. + /// An HttpResponseMessage containing the package information. public async Task GetPackageInfo(ComponentsToArtifactory component = null) { ValidateParameters(component.JfrogPackageName, component.Path); @@ -101,6 +157,11 @@ public async Task GetPackageInfo(ComponentsToArtifactory co return await ExecuteSearchAqlAsync(uri, httpContent); } + /// + /// Creates and configures an HttpClient instance with authentication settings. + /// + /// The Artifactory credentials for authentication. + /// A configured HttpClient instance. private static HttpClient GetHttpClient(ArtifactoryCredentials credentials) { var handler = new RetryHttpClientHandler() @@ -112,6 +173,12 @@ private static HttpClient GetHttpClient(ArtifactoryCredentials credentials) return httpClient; } + /// + /// Validates that at least one of the required parameters is provided. + /// + /// The package name to validate. + /// The path to validate. + /// Thrown when both packageName and path are null or empty. private static void ValidateParameters(string packageName, string path) { if (string.IsNullOrEmpty(packageName) && string.IsNullOrEmpty(path)) @@ -120,6 +187,11 @@ private static void ValidateParameters(string packageName, string path) } } + /// + /// Builds an AQL query string based on the component type and properties. + /// + /// The component containing query parameters. + /// A formatted AQL query string appropriate for the component type. public static string BuildAqlQuery(ComponentsToArtifactory component) { // Use a single helper for repeated AQL query construction @@ -161,7 +233,12 @@ public static string BuildAqlQuery(ComponentsToArtifactory component) } } - // Helper for NPM/Python AQL query + /// + /// Builds an AQL query string with specified repository and field-value pairs. + /// + /// The name of the repository to query. + /// An array of field-value tuples to include in the query. + /// A formatted AQL query string. private static string BuildAqlQueryWithFields(string repoName, (string field, string value)[] fields) { var queryList = new List { $"\"repo\":{{\"$eq\":\"{repoName}\"}}" }; @@ -173,6 +250,12 @@ private static string BuildAqlQueryWithFields(string repoName, (string field, st return $"items.find({{{string.Join(", ", queryList)}}}).include(\"repo\", \"path\", \"name\")"; } + /// + /// Asynchronously executes an AQL search query against the Artifactory server. + /// + /// The URI endpoint for the AQL search. + /// The HTTP content containing the AQL query. + /// An HttpResponseMessage containing the search results. private async Task ExecuteSearchAqlAsync(string uri, HttpContent httpContent) { HttpClient httpClient = GetHttpClient(ArtifactoryCredentials); @@ -182,6 +265,6 @@ private async Task ExecuteSearchAqlAsync(string uri, HttpCo return await httpClient.PostAsync(uri, httpContent); } - + #endregion Methods } } diff --git a/src/LCT.APICommunications/MavenJfrogApiCommunication.cs b/src/LCT.APICommunications/MavenJfrogApiCommunication.cs index 92692acb9..552719045 100644 --- a/src/LCT.APICommunications/MavenJfrogApiCommunication.cs +++ b/src/LCT.APICommunications/MavenJfrogApiCommunication.cs @@ -1,4 +1,4 @@ -// -------------------------------------------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------------------------------------------- // SPDX-FileCopyrightText: 2025 Siemens AG // // SPDX-License-Identifier: MIT @@ -13,13 +13,43 @@ namespace LCT.APICommunications { + /// + /// Provides Maven-specific JFrog Artifactory API communication operations. + /// public class MavenJfrogApiCommunication : JfrogApicommunication { + #region Properties + + /// + /// Gets or sets the timeout in seconds for HTTP requests. + /// private static int TimeoutInSec { get; set; } + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + /// The repository domain name. + /// The source repository name. + /// The repository credentials. + /// The timeout in seconds. public MavenJfrogApiCommunication(string repoDomainName, string srcrepoName, ArtifactoryCredentials repoCredentials, int timeout) : base(repoDomainName, srcrepoName, repoCredentials, timeout) { TimeoutInSec = timeout; } + + #endregion + + #region Methods + + /// + /// Creates and configures an HTTP client with authentication. + /// + /// The artifactory credentials. + /// A configured HTTP client instance. private static HttpClient GetHttpClient(ArtifactoryCredentials credentials) { var handler = new RetryHttpClientHandler() @@ -33,6 +63,10 @@ private static HttpClient GetHttpClient(ArtifactoryCredentials credentials) return httpClient; } + /// + /// Asynchronously retrieves the API key from Artifactory. + /// + /// An HTTP response message containing the API key. public override async Task GetApiKey() { HttpClient httpClient = GetHttpClient(ArtifactoryCredentials); @@ -40,6 +74,11 @@ public override async Task GetApiKey() return await httpClient.GetAsync(url); } + /// + /// Asynchronously copies a component from a remote repository. + /// + /// The component to copy. + /// An HTTP response message indicating the result of the copy operation. public override async Task CopyFromRemoteRepo(ComponentsToArtifactory component) { HttpClient httpClient = GetHttpClient(ArtifactoryCredentials); @@ -48,6 +87,11 @@ public override async Task CopyFromRemoteRepo(ComponentsToA return await httpClient.PostAsync(component.CopyPackageApiUrl, httpContent); } + /// + /// Asynchronously moves a component from one repository to another. + /// + /// The component to move. + /// An HTTP response message indicating the result of the move operation. public override async Task MoveFromRepo(ComponentsToArtifactory component) { HttpClient httpClient = GetHttpClient(ArtifactoryCredentials); @@ -56,12 +100,23 @@ public override async Task MoveFromRepo(ComponentsToArtifac return await httpClient.PostAsync(component.MovePackageApiUrl, httpContent); } + /// + /// Asynchronously retrieves package information from Artifactory. + /// + /// The component to retrieve information for. + /// An HTTP response message containing the package information. public override async Task GetPackageInfo(ComponentsToArtifactory component) { HttpClient httpClient = GetHttpClient(ArtifactoryCredentials); return await httpClient.GetAsync(component.PackageInfoApiUrl); } + /// + /// Updates the package properties in JFrog Artifactory with the SW360 release URL. + /// + /// The SW360 release URL. + /// The destination repository name. + /// The upload arguments containing package information. public override void UpdatePackagePropertiesInJfrog(string sw360releaseUrl, string destRepoName, UploadArgs uploadArgs) { HttpClient httpClient = GetHttpClient(ArtifactoryCredentials); @@ -70,5 +125,7 @@ public override void UpdatePackagePropertiesInJfrog(string sw360releaseUrl, stri $"properties=sw360url={sw360releaseUrl}"; httpClient.PutAsync(url, httpContent); } + + #endregion } -} +} \ No newline at end of file diff --git a/src/LCT.APICommunications/Model/AQL/AqlResponse.cs b/src/LCT.APICommunications/Model/AQL/AqlResponse.cs index 9a15a063d..6f2549641 100644 --- a/src/LCT.APICommunications/Model/AQL/AqlResponse.cs +++ b/src/LCT.APICommunications/Model/AQL/AqlResponse.cs @@ -15,7 +15,14 @@ namespace LCT.APICommunications.Model.AQL [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class AqlResponse { + #region Properties + + /// + /// Gets or sets the list of AQL query results. + /// [JsonProperty("results")] public IList Results { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/AQL/AqlResult.cs b/src/LCT.APICommunications/Model/AQL/AqlResult.cs index 326cf6aeb..744e7add4 100644 --- a/src/LCT.APICommunications/Model/AQL/AqlResult.cs +++ b/src/LCT.APICommunications/Model/AQL/AqlResult.cs @@ -15,31 +15,70 @@ namespace LCT.APICommunications.Model.AQL [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class AqlResult { + #region Properties + + /// + /// Gets or sets the repository name. + /// [JsonProperty("repo")] public string Repo { get; set; } + /// + /// Gets or sets the artifact path. + /// [JsonProperty("path")] public string Path { get; set; } + /// + /// Gets or sets the artifact name. + /// [JsonProperty("name")] public string Name { get; set; } + /// + /// Gets or sets the MD5 checksum of the artifact. + /// [JsonProperty("actual_md5")] public string MD5 { get; set; } + /// + /// Gets or sets the SHA1 checksum of the artifact. + /// [JsonProperty("actual_sha1")] public string SHA1 { get; set; } + /// + /// Gets or sets the SHA256 checksum of the artifact. + /// [JsonProperty("sha256")] public string SHA256 { get; set; } + /// + /// Gets or sets the list of AQL properties. + /// public List Properties { get; set; } + #endregion Properties } + + /// + /// The AqlProperty model representing a key-value property. + /// public class AqlProperty { + #region Properties + + /// + /// Gets or sets the property key. + /// public string Key { get; set; } + + /// + /// Gets or sets the property value. + /// public string Value { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/AddLinkedRelease.cs b/src/LCT.APICommunications/Model/AddLinkedRelease.cs index 66f632c81..3d96c4ab0 100644 --- a/src/LCT.APICommunications/Model/AddLinkedRelease.cs +++ b/src/LCT.APICommunications/Model/AddLinkedRelease.cs @@ -8,14 +8,26 @@ namespace LCT.APICommunications.Model { - + /// + /// Represents information for adding a linked release. + /// [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class AddLinkedRelease { + #region Properties + + /// + /// Gets or sets the release relation type. + /// [JsonProperty("releaseRelation")] public string ReleaseRelation { get; set; } + /// + /// Gets or sets the comment for the linked release. + /// [JsonProperty("comment")] public string Comment { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/AdditionalData.cs b/src/LCT.APICommunications/Model/AdditionalData.cs index 6e94fe9d2..3b3c8b81d 100644 --- a/src/LCT.APICommunications/Model/AdditionalData.cs +++ b/src/LCT.APICommunications/Model/AdditionalData.cs @@ -11,12 +11,18 @@ namespace LCT.APICommunications.Model /// /// AdditionalData model /// - [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] [DataContract] public class AdditionalData { + #region Properties + + /// + /// Gets or sets the package download URL. + /// [DataMember(Name = "package download url")] public string Download_url { get; set; } + + #endregion Properties } } \ No newline at end of file diff --git a/src/LCT.APICommunications/Model/AllProjectsEmbedded.cs b/src/LCT.APICommunications/Model/AllProjectsEmbedded.cs index 17166d375..e5481f8b3 100644 --- a/src/LCT.APICommunications/Model/AllProjectsEmbedded.cs +++ b/src/LCT.APICommunications/Model/AllProjectsEmbedded.cs @@ -15,8 +15,14 @@ namespace LCT.APICommunications.Model [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class AllProjectsEmbedded { + #region Properties + + /// + /// Gets or sets the list of all SW360 projects. + /// [JsonProperty("sw360:projects")] public IList Sw360Allprojects { get; set; } - } + #endregion Properties + } } diff --git a/src/LCT.APICommunications/Model/AllProjectsMapper.cs b/src/LCT.APICommunications/Model/AllProjectsMapper.cs index c9d1c7320..51af477b3 100644 --- a/src/LCT.APICommunications/Model/AllProjectsMapper.cs +++ b/src/LCT.APICommunications/Model/AllProjectsMapper.cs @@ -14,7 +14,14 @@ namespace LCT.APICommunications.Model [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class AllProjectsMapper { + #region Properties + + /// + /// Gets or sets the embedded projects data. + /// [JsonProperty("_embedded")] public AllProjectsEmbedded Embedded { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/ArtifactoryCredentials.cs b/src/LCT.APICommunications/Model/ArtifactoryCredentials.cs index ea7162820..d66e981f4 100644 --- a/src/LCT.APICommunications/Model/ArtifactoryCredentials.cs +++ b/src/LCT.APICommunications/Model/ArtifactoryCredentials.cs @@ -6,9 +6,19 @@ namespace LCT.APICommunications.Model { + /// + /// Represents Artifactory authentication credentials. + /// [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class ArtifactoryCredentials { + #region Properties + + /// + /// Gets or sets the authentication token. + /// public string Token { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/AttachReport.cs b/src/LCT.APICommunications/Model/AttachReport.cs index 367e64956..bd14f78a5 100644 --- a/src/LCT.APICommunications/Model/AttachReport.cs +++ b/src/LCT.APICommunications/Model/AttachReport.cs @@ -12,14 +12,33 @@ namespace LCT.APICommunications.Model [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class AttachReport { + #region Properties + + /// + /// Gets or sets the release identifier. + /// public string ReleaseId { get; set; } + /// + /// Gets or sets the attachment type. + /// public string AttachmentType { get; set; } + /// + /// Gets or sets the attachment file path. + /// public string AttachmentFile { get; set; } + /// + /// Gets or sets the attachment check status. + /// public string AttachmentCheckStatus { get; set; } + /// + /// Gets or sets the attachment release comment. + /// public string AttachmentReleaseComment { get; set; } = string.Empty; + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/AttachmentEmbedded.cs b/src/LCT.APICommunications/Model/AttachmentEmbedded.cs index 02df90b3e..416407b55 100644 --- a/src/LCT.APICommunications/Model/AttachmentEmbedded.cs +++ b/src/LCT.APICommunications/Model/AttachmentEmbedded.cs @@ -15,7 +15,14 @@ namespace LCT.APICommunications.Model [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class AttachmentEmbedded { + #region Properties + + /// + /// Gets or sets the list of SW360 attachments. + /// [JsonProperty("sw360:attachments")] public IList Sw360attachments { get; set; } + + #endregion Properties } } \ No newline at end of file diff --git a/src/LCT.APICommunications/Model/AttachmentJson.cs b/src/LCT.APICommunications/Model/AttachmentJson.cs index 841873fe8..bb83f4147 100644 --- a/src/LCT.APICommunications/Model/AttachmentJson.cs +++ b/src/LCT.APICommunications/Model/AttachmentJson.cs @@ -16,19 +16,38 @@ namespace LCT.APICommunications.Model [Serializable] public class AttachmentJson { + #region Properties + + /// + /// Gets or sets the filename of the attachment. + /// [JsonProperty("filename")] public string Filename { get; set; } + /// + /// Gets or sets the attachment content identifier. + /// [JsonProperty("attachmentContentId")] public string AttachmentContentId { get; set; } + /// + /// Gets or sets the attachment type. + /// [JsonProperty("attachmentType")] public string AttachmentType { get; set; } + /// + /// Gets or sets the check status of the attachment. + /// [JsonProperty("checkStatus")] public string CheckStatus { get; set; } + /// + /// Gets or sets the comment provided when the attachment was created. + /// [JsonProperty("createdComment")] public string CreatedComment { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/AttachmentLinks.cs b/src/LCT.APICommunications/Model/AttachmentLinks.cs index 9284525cf..ff4379258 100644 --- a/src/LCT.APICommunications/Model/AttachmentLinks.cs +++ b/src/LCT.APICommunications/Model/AttachmentLinks.cs @@ -14,8 +14,23 @@ namespace LCT.APICommunications.Model [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class AttachmentLinks { + #region Properties + + /// + /// Gets or sets the SW360 component reference. + /// public Sw360Href Sw360component { get; set; } + + /// + /// Gets or sets the self reference link. + /// public Self Self { get; set; } + + /// + /// Gets or sets the list of CURIES (Compact URI) definitions. + /// public IList Curies { get; set; } + + #endregion Properties } } \ No newline at end of file diff --git a/src/LCT.APICommunications/Model/Checksum.cs b/src/LCT.APICommunications/Model/Checksum.cs index 95d5de3b5..c8c4c59f7 100644 --- a/src/LCT.APICommunications/Model/Checksum.cs +++ b/src/LCT.APICommunications/Model/Checksum.cs @@ -8,10 +8,20 @@ namespace LCT.APICommunications.Model { + /// + /// Represents checksum information for a file or package. + /// [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class Checksum { + #region Properties + + /// + /// Gets or sets the SHA1 hash value. + /// [JsonProperty("sha1")] public string Sha1 { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/ClearingStatus.cs b/src/LCT.APICommunications/Model/ClearingStatus.cs index 382b34e2f..9a7f1cc3c 100644 --- a/src/LCT.APICommunications/Model/ClearingStatus.cs +++ b/src/LCT.APICommunications/Model/ClearingStatus.cs @@ -12,45 +12,83 @@ namespace LCT.APICommunications.Model /// /// The ReleasesInfo model /// - [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class ReleasesInfo { + #region Properties + + /// + /// Gets or sets the release name. + /// [JsonProperty("name")] public string Name { get; set; } + /// + /// Gets or sets the release version. + /// [JsonProperty("version")] public string Version { get; set; } + /// + /// Gets or sets the clearing state of the release. + /// [JsonProperty("clearingState")] public string ClearingState { get; set; } + /// + /// Gets or sets the source code download URL. + /// [JsonProperty("sourceCodeDownloadurl")] public string SourceCodeDownloadUrl { get; set; } - + /// + /// Gets or sets the binary download URL. + /// [JsonProperty("binaryDownloadurl")] public string BinaryDownloadUrl { get; set; } + /// + /// Gets or sets the creator of the release. + /// [JsonProperty("createdBy")] public string CreatedBy { get; set; } + /// + /// Gets or sets the ECC (Export Control Classification) information. + /// [JsonProperty("eccInformation")] public EccInformation EccInformation { get; set; } + /// + /// Gets or sets the links associated with the release. + /// [JsonProperty("_links")] public ReleaseLinks Links { get; set; } + /// + /// Gets or sets additional data as key-value pairs. + /// [JsonProperty("additionalData")] public Dictionary AdditionalData { get; set; } + /// + /// Gets or sets the external identifiers as key-value pairs. + /// [JsonProperty("externalIds")] public Dictionary ExternalIds { get; set; } + /// + /// Gets or sets the embedded attachment data. + /// [JsonProperty("_embedded")] public AttachmentEmbedded Embedded { get; set; } + + /// + /// Gets or sets the list of external tool processes. + /// [JsonProperty("externalToolProcesses")] public List ExternalToolProcesses { get; set; } + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/ComponentEmbedded.cs b/src/LCT.APICommunications/Model/ComponentEmbedded.cs index 31efa90f2..e689926e5 100644 --- a/src/LCT.APICommunications/Model/ComponentEmbedded.cs +++ b/src/LCT.APICommunications/Model/ComponentEmbedded.cs @@ -15,7 +15,14 @@ namespace LCT.APICommunications.Model [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class ComponentEmbedded { + #region Properties + + /// + /// Gets or sets the list of SW360 components. + /// [JsonProperty("sw360:components")] public IList Sw360components { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/ComponentPurlId.cs b/src/LCT.APICommunications/Model/ComponentPurlId.cs index 191ce5c55..d069171c0 100644 --- a/src/LCT.APICommunications/Model/ComponentPurlId.cs +++ b/src/LCT.APICommunications/Model/ComponentPurlId.cs @@ -12,12 +12,17 @@ namespace LCT.APICommunications.Model /// /// The Component Level Purl id model /// - /// - [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class ComponentPurlId { + #region Properties + + /// + /// Gets or sets the external identifiers as key-value pairs. + /// [JsonProperty("externalIds")] public Dictionary ExternalIds { get; set; } + + #endregion Properties } } \ No newline at end of file diff --git a/src/LCT.APICommunications/Model/ComponentStatus.cs b/src/LCT.APICommunications/Model/ComponentStatus.cs index 1918b051c..893aa19b9 100644 --- a/src/LCT.APICommunications/Model/ComponentStatus.cs +++ b/src/LCT.APICommunications/Model/ComponentStatus.cs @@ -6,11 +6,24 @@ namespace LCT.APICommunications.Model { - + /// + /// Represents the status of a component. + /// [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class ComponentStatus { + #region Properties + + /// + /// Gets or sets the SW360 components information. + /// public Sw360Components Sw360components { get; set; } + + /// + /// Gets or sets a value indicating whether the component exists. + /// public bool isComponentExist { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/ComponentTypeData.cs b/src/LCT.APICommunications/Model/ComponentTypeData.cs index 7451b6690..1c95d079e 100644 --- a/src/LCT.APICommunications/Model/ComponentTypeData.cs +++ b/src/LCT.APICommunications/Model/ComponentTypeData.cs @@ -8,10 +8,20 @@ namespace LCT.APICommunications.Model { + /// + /// Represents component type data with embedded component information. + /// [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class ComponentTypeData { + #region Properties + + /// + /// Gets or sets the embedded component information. + /// [JsonProperty("_embedded")] public ComponentEmbedded Embedded { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/ComponentsDetailData.cs b/src/LCT.APICommunications/Model/ComponentsDetailData.cs index 63359a3f3..e6cd18c70 100644 --- a/src/LCT.APICommunications/Model/ComponentsDetailData.cs +++ b/src/LCT.APICommunications/Model/ComponentsDetailData.cs @@ -15,52 +15,104 @@ namespace LCT.APICommunications.Model [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class ComponentsDetailData { + #region Properties + + /// + /// Gets or sets the component name. + /// [JsonProperty("name")] public string Name { get; set; } + /// + /// Gets or sets the component description. + /// [JsonProperty("description")] public string Description { get; set; } + /// + /// Gets or sets the creation date of the component. + /// [JsonProperty("createdOn")] public string CreatedOn { get; set; } + /// + /// Gets or sets the component type. + /// [JsonProperty("componentType")] public string ComponentType { get; set; } + /// + /// Gets or sets the component owner. + /// [JsonProperty("componentOwner")] public string ComponentOwner { get; set; } + /// + /// Gets or sets the owner's accounting unit. + /// [JsonProperty("ownerAccountingUnit")] public string OwnerAccountingUnit { get; set; } + /// + /// Gets or sets the owner's country. + /// [JsonProperty("ownerCountry")] public string OwnerCountry { get; set; } + /// + /// Gets or sets the owner's group. + /// [JsonProperty("ownerGroup")] public string OwnerGroup { get; set; } + /// + /// Gets or sets the roles associated with the component. + /// [JsonProperty("roles")] public Roles Roles { get; set; } + /// + /// Gets or sets the list of categories. + /// [JsonProperty("categories")] public IList Categories { get; set; } + /// + /// Gets or sets the list of programming languages. + /// [JsonProperty("languages")] public IList Languages { get; set; } + /// + /// Gets or sets the list of operating systems. + /// [JsonProperty("operatingSystems")] public IList OperatingSystems { get; set; } + /// + /// Gets or sets the homepage URL. + /// [JsonProperty("homepage")] public string Homepage { get; set; } + /// + /// Gets or sets the mailing list address. + /// [JsonProperty("mailinglist")] public string Mailinglist { get; set; } + /// + /// Gets or sets the embedded component details data. + /// [JsonProperty("_embedded")] public ComponentsDetailEmbedded Embedded { get; set; } + /// + /// Gets or sets the links associated with the component. + /// [JsonProperty("_links")] public Links Links { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/ComponentsDetailEmbedded.cs b/src/LCT.APICommunications/Model/ComponentsDetailEmbedded.cs index 47b16981b..12bdf1af6 100644 --- a/src/LCT.APICommunications/Model/ComponentsDetailEmbedded.cs +++ b/src/LCT.APICommunications/Model/ComponentsDetailEmbedded.cs @@ -9,13 +9,26 @@ namespace LCT.APICommunications.Model { + /// + /// Represents embedded component details data. + /// [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class ComponentsDetailEmbedded { + #region Properties + + /// + /// Gets or sets the creator information. + /// [JsonProperty("createdBy")] public CreatedBy CreatedBy { get; set; } + /// + /// Gets or sets the list of SW360 releases. + /// [JsonProperty("sw360:releases")] public IList Sw360Releases { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/ComponentsModel.cs b/src/LCT.APICommunications/Model/ComponentsModel.cs index 0801c617f..bd00b5d62 100644 --- a/src/LCT.APICommunications/Model/ComponentsModel.cs +++ b/src/LCT.APICommunications/Model/ComponentsModel.cs @@ -11,11 +11,17 @@ namespace LCT.APICommunications.Model /// /// ComponentsModel /// - [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class ComponentsModel { + #region Properties + + /// + /// Gets or sets the embedded component data. + /// [JsonProperty("_embedded")] public ComponentEmbedded Embedded { get; set; } + + #endregion Properties } } \ No newline at end of file diff --git a/src/LCT.APICommunications/Model/ComponentsRelease.cs b/src/LCT.APICommunications/Model/ComponentsRelease.cs index 1a8e6c45e..f359a5549 100644 --- a/src/LCT.APICommunications/Model/ComponentsRelease.cs +++ b/src/LCT.APICommunications/Model/ComponentsRelease.cs @@ -14,7 +14,14 @@ namespace LCT.APICommunications.Model [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class ComponentsRelease { + #region Properties + + /// + /// Gets or sets the embedded release data. + /// [JsonProperty("_embedded")] public ReleaseEmbedded Embedded { get; set; } + + #endregion Properties } } \ No newline at end of file diff --git a/src/LCT.APICommunications/Model/ComponentsToArtifactory.cs b/src/LCT.APICommunications/Model/ComponentsToArtifactory.cs index 543835395..25d09f4ba 100644 --- a/src/LCT.APICommunications/Model/ComponentsToArtifactory.cs +++ b/src/LCT.APICommunications/Model/ComponentsToArtifactory.cs @@ -8,32 +8,129 @@ namespace LCT.APICommunications.Model { - + /// + /// Represents component information for Artifactory upload operations. + /// [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class ComponentsToArtifactory { + #region Properties + + /// + /// Gets or sets the component name. + /// public string Name { get; set; } + + /// + /// Gets or sets the package name. + /// public string PackageName { get; set; } + + /// + /// Gets or sets the component version. + /// public string Version { get; set; } + + /// + /// Gets or sets the component type. + /// public string ComponentType { get; set; } + + /// + /// Gets or sets the JFrog API URL. + /// public string JfrogApi { get; set; } + + /// + /// Gets or sets the source repository name. + /// public string SrcRepoName { get; set; } + + /// + /// Gets or sets the source repository path with full name. + /// public string SrcRepoPathWithFullName { get; set; } + + /// + /// Gets or sets the PyPI or NPM component name. + /// public string PypiOrNpmCompName { get; set; } + + /// + /// Gets or sets the destination repository name. + /// public string DestRepoName { get; set; } + + /// + /// Gets or sets the authentication token. + /// public string Token { get; set; } + + /// + /// Gets or sets the package information API URL. + /// public string PackageInfoApiUrl { get; set; } + + /// + /// Gets or sets the copy package API URL. + /// public string CopyPackageApiUrl { get; set; } + + /// + /// Gets or sets the move package API URL. + /// public string MovePackageApiUrl { get; set; } + + /// + /// Gets or sets the package file extension. + /// public string PackageExtension { get; set; } + + /// + /// Gets or sets the package path. + /// public string Path { get; set; } + + /// + /// Gets or sets the package type. + /// public PackageType PackageType { get; set; } + + /// + /// Gets or sets a value indicating whether this is a dry run operation. + /// public bool DryRun { get; set; } = true; + + /// + /// Gets or sets the package URL (PURL). + /// public string Purl { get; set; } + + /// + /// Gets or sets the JFrog package name. + /// public string JfrogPackageName { get; set; } + + /// + /// Gets or sets the operation type. + /// public string OperationType { get; set; } + + /// + /// Gets or sets the dry run suffix. + /// public string DryRunSuffix { get; set; } + + /// + /// Gets or sets the JFrog repository path. + /// public string JfrogRepoPath { get; set; } + + /// + /// Gets or sets the HTTP response message. + /// public HttpResponseMessage ResponseMessage { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/CreateComponent.cs b/src/LCT.APICommunications/Model/CreateComponent.cs index 976f58f0c..316366286 100644 --- a/src/LCT.APICommunications/Model/CreateComponent.cs +++ b/src/LCT.APICommunications/Model/CreateComponent.cs @@ -14,15 +14,32 @@ namespace LCT.APICommunications.Model [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class CreateComponent { + #region Properties + + /// + /// Gets or sets the component name. + /// [JsonProperty("name")] public string Name { get; set; } + /// + /// Gets or sets the component type. + /// [JsonProperty("componentType")] public string ComponentType { get; set; } + /// + /// Gets or sets the component categories. + /// [JsonProperty("categories")] public string[] Categories { get; set; } + + /// + /// Gets or sets the external identifiers. + /// [JsonProperty("externalIds")] public ExternalIds ExternalIds { get; set; } + + #endregion Properties } } \ No newline at end of file diff --git a/src/LCT.APICommunications/Model/CreatedBy.cs b/src/LCT.APICommunications/Model/CreatedBy.cs index 9a0863a0f..44914c660 100644 --- a/src/LCT.APICommunications/Model/CreatedBy.cs +++ b/src/LCT.APICommunications/Model/CreatedBy.cs @@ -14,10 +14,20 @@ namespace LCT.APICommunications.Model [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class CreatedBy { + #region Properties + + /// + /// Gets or sets the email address. + /// [JsonProperty("email")] public string Email { get; set; } + /// + /// Gets or sets the links. + /// [JsonProperty("_links")] public Links Links { get; set; } + + #endregion Properties } } \ No newline at end of file diff --git a/src/LCT.APICommunications/Model/Cury.cs b/src/LCT.APICommunications/Model/Cury.cs index 9a2c7cd7b..585e6c20f 100644 --- a/src/LCT.APICommunications/Model/Cury.cs +++ b/src/LCT.APICommunications/Model/Cury.cs @@ -14,11 +14,26 @@ namespace LCT.APICommunications.Model [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class Cury { + #region Properties + + /// + /// Gets or sets the hyperlink reference. + /// [JsonProperty("href")] public string Href { get; set; } + + /// + /// Gets or sets the name. + /// [JsonProperty("name")] public string Name { get; set; } + + /// + /// Gets or sets a value indicating whether the reference is templated. + /// [JsonProperty("templated")] public bool Templated { get; set; } + + #endregion Properties } } \ No newline at end of file diff --git a/src/LCT.APICommunications/Model/Docupdate.cs b/src/LCT.APICommunications/Model/Docupdate.cs index d4f28b6ca..fedfc3ac6 100644 --- a/src/LCT.APICommunications/Model/Docupdate.cs +++ b/src/LCT.APICommunications/Model/Docupdate.cs @@ -11,11 +11,17 @@ namespace LCT.APICommunications.Model /// /// DocUpdate model /// - [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class DocUpdate { + #region Properties + + /// + /// Gets or sets the embedded attachment information. + /// [JsonProperty("_embedded")] public AttachmentEmbedded Embedded { get; set; } + + #endregion Properties } } \ No newline at end of file diff --git a/src/LCT.APICommunications/Model/EccInformation.cs b/src/LCT.APICommunications/Model/EccInformation.cs index 05c044228..3297c3b30 100644 --- a/src/LCT.APICommunications/Model/EccInformation.cs +++ b/src/LCT.APICommunications/Model/EccInformation.cs @@ -10,11 +10,18 @@ namespace LCT.APICommunications.Model { /// /// The EccInformation model - /// + /// [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class EccInformation { + #region Properties + + /// + /// Gets or sets the ECC status. + /// [JsonProperty("eccStatus")] public string EccStatus { get; set; } + + #endregion Properties } } \ No newline at end of file diff --git a/src/LCT.APICommunications/Model/ExternalIds.cs b/src/LCT.APICommunications/Model/ExternalIds.cs index a3018c135..58ef6dd46 100644 --- a/src/LCT.APICommunications/Model/ExternalIds.cs +++ b/src/LCT.APICommunications/Model/ExternalIds.cs @@ -10,18 +10,25 @@ namespace LCT.APICommunications.Model { /// /// ExternalIds model - /// - /// - - + /// [DataContract] [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class ExternalIds { + #region Properties + + /// + /// Gets or sets the PURL identifier. + /// [DataMember(Name = "purl.id")] public string Purl_Id { get; set; } + /// + /// Gets or sets the package URL. + /// [DataMember(Name = "package-url")] public string Package_Url { get; set; } + + #endregion Properties } } \ No newline at end of file diff --git a/src/LCT.APICommunications/Model/ExternalToolProcess.cs b/src/LCT.APICommunications/Model/ExternalToolProcess.cs index 8c810ccec..3097302d8 100644 --- a/src/LCT.APICommunications/Model/ExternalToolProcess.cs +++ b/src/LCT.APICommunications/Model/ExternalToolProcess.cs @@ -10,22 +10,44 @@ namespace LCT.APICommunications.Model { + /// + /// Represents external tool processing information. + /// [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class ExternalToolProcess { + #region Properties + + /// + /// Gets or sets the external tool name. + /// [JsonProperty("externalTool")] public string ExternalTool { get; set; } + /// + /// Gets or sets the process status. + /// [JsonProperty("processStatus")] public string ProcessStatus { get; set; } + /// + /// Gets or sets the attachment identifier. + /// [JsonProperty("attachmentId")] public string AttachmentId { get; set; } + /// + /// Gets or sets the attachment hash. + /// [JsonProperty("attachmentHash")] public string AttachmentHash { get; set; } + /// + /// Gets or sets the list of process steps. + /// [JsonProperty("processSteps")] public List ProcessSteps { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/Foss/Analysis.cs b/src/LCT.APICommunications/Model/Foss/Analysis.cs index 09cdfcdc4..2b3fa7181 100644 --- a/src/LCT.APICommunications/Model/Foss/Analysis.cs +++ b/src/LCT.APICommunications/Model/Foss/Analysis.cs @@ -11,41 +11,76 @@ namespace LCT.APICommunications.Model.Foss /// /// Fossology Analyzer model /// - /// - [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class Analysis { + #region Properties + + /// + /// Gets or sets a value indicating whether bucket analysis is enabled. + /// [JsonProperty("bucket")] public bool Bucket { get; set; } + /// + /// Gets or sets a value indicating whether copyright email author analysis is enabled. + /// [JsonProperty("copyright_email_author")] public bool Copyright_email_author { get; set; } + /// + /// Gets or sets a value indicating whether ECC (Export Control Classification) analysis is enabled. + /// [JsonProperty("ecc")] public bool Ecc { get; set; } + /// + /// Gets or sets a value indicating whether keyword analysis is enabled. + /// [JsonProperty("keyword")] public bool Keyword { get; set; } + /// + /// Gets or sets a value indicating whether MIME type analysis is enabled. + /// [JsonProperty("mime")] public bool Mime { get; set; } + /// + /// Gets or sets a value indicating whether Monk license scanner is enabled. + /// [JsonProperty("monk")] public bool Monk { get; set; } + /// + /// Gets or sets a value indicating whether Nomos license scanner is enabled. + /// [JsonProperty("nomos")] public bool Nomos { get; set; } + /// + /// Gets or sets a value indicating whether Ojo license scanner is enabled. + /// [JsonProperty("ojo")] public bool Ojo { get; set; } + /// + /// Gets or sets a value indicating whether package analysis is enabled. + /// [JsonProperty("package")] public bool Package { get; set; } + #endregion Properties + + #region Constructors + + /// + /// Initializes a new instance of the class. + /// public Analysis() { - } + + #endregion Constructors } } diff --git a/src/LCT.APICommunications/Model/Foss/AttachBy.cs b/src/LCT.APICommunications/Model/Foss/AttachBy.cs index 31b7abfb9..26b6e6d08 100644 --- a/src/LCT.APICommunications/Model/Foss/AttachBy.cs +++ b/src/LCT.APICommunications/Model/Foss/AttachBy.cs @@ -8,10 +8,20 @@ namespace LCT.APICommunications.Model.Foss { + /// + /// Represents attachment creator information. + /// [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class AttachBy { + #region Properties + + /// + /// Gets or sets the creator information for the attachment. + /// [JsonProperty("createdBy")] public AttachCreatedBy CreatedBy { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/Foss/AttachCreatedBy.cs b/src/LCT.APICommunications/Model/Foss/AttachCreatedBy.cs index 1c25e6090..307d33efe 100644 --- a/src/LCT.APICommunications/Model/Foss/AttachCreatedBy.cs +++ b/src/LCT.APICommunications/Model/Foss/AttachCreatedBy.cs @@ -11,14 +11,23 @@ namespace LCT.APICommunications.Model.Foss /// /// AttachCreatedBy model class /// - [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class AttachCreatedBy { + #region Properties + + /// + /// Gets or sets the name of the creator. + /// [JsonProperty("name")] public string Name { get; set; } + /// + /// Gets or sets the links associated with the creator. + /// [JsonProperty("_links")] public Links Links { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/Foss/AttachmentLink.cs b/src/LCT.APICommunications/Model/Foss/AttachmentLink.cs index aba612827..326d480f6 100644 --- a/src/LCT.APICommunications/Model/Foss/AttachmentLink.cs +++ b/src/LCT.APICommunications/Model/Foss/AttachmentLink.cs @@ -12,44 +12,83 @@ namespace LCT.APICommunications.Model.Foss /// /// AttachmentLink class /// - [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class AttachmentLink { + #region Properties + + /// + /// Gets or sets the filename of the attachment. + /// [JsonProperty("filename")] public string Filename { get; set; } + /// + /// Gets or sets the SHA1 hash of the attachment. + /// [JsonProperty("sha1")] public string Sha1 { get; set; } + /// + /// Gets or sets the attachment type. + /// [JsonProperty("attachmentType")] public string AttachmentType { get; set; } + /// + /// Gets or sets the creator of the attachment. + /// [JsonProperty("createdBy")] public string CreatedBy { get; set; } + /// + /// Gets or sets the team that created the attachment. + /// [JsonProperty("createdTeam")] public string CreatedTeam { get; set; } + /// + /// Gets or sets the comment provided when the attachment was created. + /// [JsonProperty("createdComment")] public string CreatedComment { get; set; } + /// + /// Gets or sets the creation date of the attachment. + /// [JsonProperty("createdOn")] public string CreatedOn { get; set; } + /// + /// Gets or sets the comment provided when the attachment was checked. + /// [JsonProperty("checkedComment")] public string CheckedComment { get; set; } + /// + /// Gets or sets the check status of the attachment. + /// [JsonProperty("checkStatus")] public string CheckStatus { get; set; } + /// + /// Gets or sets the SW360 download links for the attachment. + /// [JsonProperty("_links")] public SW360DownloadLinks Links { get; set; } + /// + /// Gets or sets the self reference link. + /// [JsonProperty("self")] public Self Self { get; set; } + /// + /// Gets or sets the list of CURIES (Compact URI) definitions. + /// [JsonProperty("curies")] public IList Curies { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/Foss/CheckFossologyProcess.cs b/src/LCT.APICommunications/Model/Foss/CheckFossologyProcess.cs index 281381e57..5a28dddef 100644 --- a/src/LCT.APICommunications/Model/Foss/CheckFossologyProcess.cs +++ b/src/LCT.APICommunications/Model/Foss/CheckFossologyProcess.cs @@ -8,14 +8,26 @@ namespace LCT.APICommunications.Model.Foss { - + /// + /// Represents the Fossology process status check information. + /// [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class CheckFossologyProcess { + #region Properties + + /// + /// Gets or sets the Fossology process information. + /// [JsonProperty("fossologyProcessInfo")] public FossologyProcessInfo FossologyProcessInfo { get; set; } + + /// + /// Gets or sets the status of the Fossology process. + /// [JsonProperty("status")] public string Status { get; set; } + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/Foss/Content.cs b/src/LCT.APICommunications/Model/Foss/Content.cs index 4a5187e13..72dc40ddd 100644 --- a/src/LCT.APICommunications/Model/Foss/Content.cs +++ b/src/LCT.APICommunications/Model/Foss/Content.cs @@ -8,11 +8,20 @@ namespace LCT.APICommunications.Model.Foss { - + /// + /// Represents content with a message. + /// [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class Content { + #region Properties + + /// + /// Gets or sets the message content. + /// [JsonProperty("message")] public string Message { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/Foss/Decider.cs b/src/LCT.APICommunications/Model/Foss/Decider.cs index 753031fa2..7baae9c45 100644 --- a/src/LCT.APICommunications/Model/Foss/Decider.cs +++ b/src/LCT.APICommunications/Model/Foss/Decider.cs @@ -11,25 +11,46 @@ namespace LCT.APICommunications.Model.Foss /// /// Fossoloygy decider model /// - [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class Decider { + #region Properties + + /// + /// Gets or sets a value indicating whether the Nomos-Monk decider is enabled. + /// [JsonProperty("nomos_monk")] public bool Nomos_monk { get; set; } + /// + /// Gets or sets a value indicating whether bulk reused decider is enabled. + /// [JsonProperty("bulk_reused")] public bool Bulk_reused { get; set; } + /// + /// Gets or sets a value indicating whether the new scanner decider is enabled. + /// [JsonProperty("new_scanner")] public bool New_scanner { get; set; } + /// + /// Gets or sets a value indicating whether the Ojo decider is enabled. + /// [JsonProperty("ojo_decider")] public bool Ojo_decider { get; set; } + #endregion Properties + + #region Constructors + + /// + /// Initializes a new instance of the class. + /// public Decider() { - } + + #endregion Constructors } } diff --git a/src/LCT.APICommunications/Model/Foss/FileUpload.cs b/src/LCT.APICommunications/Model/Foss/FileUpload.cs index bd2570080..a4e5d8be7 100644 --- a/src/LCT.APICommunications/Model/Foss/FileUpload.cs +++ b/src/LCT.APICommunications/Model/Foss/FileUpload.cs @@ -11,29 +11,53 @@ namespace LCT.APICommunications.Model.Foss /// /// File upload Model /// - [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class FileUpload { + #region Properties + + /// + /// Gets or sets the folder identifier. + /// [JsonProperty("folderid")] public string FolderId { get; set; } + /// + /// Gets or sets the folder name. + /// [JsonProperty("foldername")] public string Foldername { get; set; } + /// + /// Gets or sets the upload identifier. + /// [JsonProperty("id")] public string UploadId { get; set; } + /// + /// Gets or sets the description of the upload. + /// [JsonProperty("description")] public string Description { get; set; } + /// + /// Gets or sets the upload name. + /// [JsonProperty("uploadname")] public string UploadName { get; set; } + /// + /// Gets or sets the upload date. + /// [JsonProperty("uploaddate")] public string UploadDate { get; set; } + /// + /// Gets or sets the file upload hash information. + /// [JsonProperty("hash")] public FileUploadHash FileUploadHash { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/Foss/FileUploadHash.cs b/src/LCT.APICommunications/Model/Foss/FileUploadHash.cs index 1fee98d5a..e2f42077f 100644 --- a/src/LCT.APICommunications/Model/Foss/FileUploadHash.cs +++ b/src/LCT.APICommunications/Model/Foss/FileUploadHash.cs @@ -11,20 +11,35 @@ namespace LCT.APICommunications.Model.Foss /// /// Then File upload hash code model /// - [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class FileUploadHash { + #region Properties + + /// + /// Gets or sets the SHA1 hash of the uploaded file. + /// [JsonProperty("sha1")] public string Sha1 { get; set; } + /// + /// Gets or sets the MD5 hash of the uploaded file. + /// [JsonProperty("md5")] public string Md5 { get; set; } + /// + /// Gets or sets the SHA256 hash of the uploaded file. + /// [JsonProperty("sha256")] public string Sha256 { get; set; } + /// + /// Gets or sets the size of the uploaded file. + /// [JsonProperty("size")] public string Size { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/Foss/FolderModel.cs b/src/LCT.APICommunications/Model/Foss/FolderModel.cs index 4b1622376..bb84a4907 100644 --- a/src/LCT.APICommunications/Model/Foss/FolderModel.cs +++ b/src/LCT.APICommunications/Model/Foss/FolderModel.cs @@ -11,20 +11,35 @@ namespace LCT.APICommunications.Model.Foss /// /// The folder model /// - [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class FolderModel { + #region Properties + + /// + /// Gets or sets the folder identifier. + /// [JsonProperty("id")] public string Id { get; set; } + /// + /// Gets or sets the folder name. + /// [JsonProperty("name")] public string Name { get; set; } + /// + /// Gets or sets the folder description. + /// [JsonProperty("description")] public string Description { get; set; } + /// + /// Gets or sets the parent folder identifier. + /// [JsonProperty("parent")] public string Parent { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/Foss/FossTriggerStatus.cs b/src/LCT.APICommunications/Model/Foss/FossTriggerStatus.cs index f1ad6c9a6..5d0e03cdd 100644 --- a/src/LCT.APICommunications/Model/Foss/FossTriggerStatus.cs +++ b/src/LCT.APICommunications/Model/Foss/FossTriggerStatus.cs @@ -8,13 +8,26 @@ namespace LCT.APICommunications.Model.Foss { + /// + /// Represents the status response from triggering a Fossology process. + /// [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class FossTriggerStatus { + #region Properties + + /// + /// Gets or sets the content of the trigger status. + /// [JsonProperty("content")] public Content Content { get; set; } + /// + /// Gets or sets the links associated with the trigger status. + /// [JsonProperty("_links")] public Links Links { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/Foss/FossologyJobs.cs b/src/LCT.APICommunications/Model/Foss/FossologyJobs.cs index f67a9e11b..ff602fe07 100644 --- a/src/LCT.APICommunications/Model/Foss/FossologyJobs.cs +++ b/src/LCT.APICommunications/Model/Foss/FossologyJobs.cs @@ -11,17 +11,29 @@ namespace LCT.APICommunications.Model.Foss /// /// Fossology Jobs model /// - [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class FossologyJobs { + #region Properties + + /// + /// Gets or sets the analysis configuration for the Fossology job. + /// [JsonProperty("analysis")] public Analysis Analysis { get; set; } + /// + /// Gets or sets the decider configuration for the Fossology job. + /// [JsonProperty("decider")] public Decider Decider { get; set; } + /// + /// Gets or sets the reuse configuration for the Fossology job. + /// [JsonProperty("reuse")] public Reuse Reuse { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/Foss/FossologyProcessInfo.cs b/src/LCT.APICommunications/Model/Foss/FossologyProcessInfo.cs index 23499257f..59a5f25d1 100644 --- a/src/LCT.APICommunications/Model/Foss/FossologyProcessInfo.cs +++ b/src/LCT.APICommunications/Model/Foss/FossologyProcessInfo.cs @@ -8,15 +8,26 @@ namespace LCT.APICommunications.Model.Foss { - + /// + /// Represents the Fossology process information. + /// [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class FossologyProcessInfo { + #region Properties + /// + /// Gets or sets the external tool name. + /// [JsonProperty("externalTool")] public string ExternalTool { get; set; } + /// + /// Gets or sets the array of process steps. + /// [JsonProperty("processSteps")] public ProcessSteps[] ProcessSteps { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/Foss/GenReportResponse.cs b/src/LCT.APICommunications/Model/Foss/GenReportResponse.cs index 4b31ff6f8..3a32cc56b 100644 --- a/src/LCT.APICommunications/Model/Foss/GenReportResponse.cs +++ b/src/LCT.APICommunications/Model/Foss/GenReportResponse.cs @@ -14,13 +14,26 @@ namespace LCT.APICommunications.Model.Foss [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class GenReportResponse { + #region Properties + + /// + /// Gets or sets the response code. + /// [JsonProperty("code")] public int Code { get; set; } + /// + /// Gets or sets the response message. + /// [JsonProperty("message")] public string Message { get; set; } + /// + /// Gets or sets the response type. + /// [JsonProperty("type")] public string Type { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/Foss/MultipleUploadComponentModel.cs b/src/LCT.APICommunications/Model/Foss/MultipleUploadComponentModel.cs index 46f6b1a17..2f14fe287 100644 --- a/src/LCT.APICommunications/Model/Foss/MultipleUploadComponentModel.cs +++ b/src/LCT.APICommunications/Model/Foss/MultipleUploadComponentModel.cs @@ -11,29 +11,53 @@ namespace LCT.APICommunications.Model.Foss /// /// Multiple upload component model /// - [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class MultipleUploadComponentModel { + #region Properties + + /// + /// Gets or sets the folder identifier. + /// [JsonProperty("folderid")] public string Folderid { get; set; } + /// + /// Gets or sets the folder name. + /// [JsonProperty("foldername")] public string Foldername { get; set; } + /// + /// Gets or sets the upload identifier. + /// [JsonProperty("id")] public string UploadId { get; set; } + /// + /// Gets or sets the description of the upload. + /// [JsonProperty("description")] public string Description { get; set; } + /// + /// Gets or sets the upload name. + /// [JsonProperty("uploadname")] public string Uploadname { get; set; } + /// + /// Gets or sets the upload date. + /// [JsonProperty("uploaddate")] public string Uploaddate { get; set; } + /// + /// Gets or sets the file size. + /// [JsonProperty("filesize")] public string Filesize { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/Foss/ProcessSteps.cs b/src/LCT.APICommunications/Model/Foss/ProcessSteps.cs index e8bf53f75..5264942d0 100644 --- a/src/LCT.APICommunications/Model/Foss/ProcessSteps.cs +++ b/src/LCT.APICommunications/Model/Foss/ProcessSteps.cs @@ -8,20 +8,38 @@ namespace LCT.APICommunications.Model.Foss { - + /// + /// Represents a single step in a Fossology process. + /// [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class ProcessSteps { + #region Properties + + /// + /// Gets or sets the name of the process step. + /// [JsonProperty("stepName")] public string StepName { get; set; } + /// + /// Gets or sets the status of the process step. + /// [JsonProperty("stepStatus")] public string StepStatus { get; set; } + /// + /// Gets or sets the process step identifier in the external tool. + /// [JsonProperty("processStepIdInTool")] public string ProcessStepIdInTool { get; set; } + /// + /// Gets or sets the result of the process step. + /// [JsonProperty("result")] public string Result { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/Foss/ReleaseAttachments.cs b/src/LCT.APICommunications/Model/Foss/ReleaseAttachments.cs index b47a5c9a2..1d22acac4 100644 --- a/src/LCT.APICommunications/Model/Foss/ReleaseAttachments.cs +++ b/src/LCT.APICommunications/Model/Foss/ReleaseAttachments.cs @@ -11,11 +11,17 @@ namespace LCT.APICommunications.Model.Foss /// /// Release Attachment model /// - [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class ReleaseAttachments { + #region Properties + + /// + /// Gets or sets the embedded attachment data. + /// [JsonProperty("_embedded")] public AttachmentEmbedded Embedded { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/Foss/Reuse.cs b/src/LCT.APICommunications/Model/Foss/Reuse.cs index c76470469..aa90b115f 100644 --- a/src/LCT.APICommunications/Model/Foss/Reuse.cs +++ b/src/LCT.APICommunications/Model/Foss/Reuse.cs @@ -11,20 +11,35 @@ namespace LCT.APICommunications.Model.Foss /// /// Reuse scanner model /// - [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class Reuse { + #region Properties + + /// + /// Gets or sets the reuse upload identifier. + /// [JsonProperty("reuse_upload")] public int Reuse_upload { get; set; } + /// + /// Gets or sets the reuse group identifier. + /// [JsonProperty("reuse_group")] public int Reuse_group { get; set; } + /// + /// Gets or sets a value indicating whether main reuse is enabled. + /// [JsonProperty("reuse_main")] public bool Reuse_main { get; set; } + /// + /// Gets or sets a value indicating whether enhanced reuse is enabled. + /// [JsonProperty("reuse_enhanced")] public bool Reuse_enhanced { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/Foss/SW360DownloadHref.cs b/src/LCT.APICommunications/Model/Foss/SW360DownloadHref.cs index fdcdc2365..7a9968555 100644 --- a/src/LCT.APICommunications/Model/Foss/SW360DownloadHref.cs +++ b/src/LCT.APICommunications/Model/Foss/SW360DownloadHref.cs @@ -11,12 +11,17 @@ namespace LCT.APICommunications.Model.Foss /// /// The SW360DownloadHref model /// - [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class SW360DownloadHref { + #region Properties + /// + /// Gets or sets the download URL. + /// [JsonProperty("href")] public string DownloadUrl { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/Foss/SW360DownloadLinks.cs b/src/LCT.APICommunications/Model/Foss/SW360DownloadLinks.cs index cb89f6c18..aeb2fd38a 100644 --- a/src/LCT.APICommunications/Model/Foss/SW360DownloadLinks.cs +++ b/src/LCT.APICommunications/Model/Foss/SW360DownloadLinks.cs @@ -11,11 +11,17 @@ namespace LCT.APICommunications.Model.Foss /// /// The SW360DownloadLinks model /// - [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class SW360DownloadLinks { + #region Properties + + /// + /// Gets or sets the SW360 download link. + /// [JsonProperty("sw360:downloadLink")] public SW360DownloadHref Sw360DownloadLink { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/Foss/SW360Releases.cs b/src/LCT.APICommunications/Model/Foss/SW360Releases.cs index f27d8a65d..9368267da 100644 --- a/src/LCT.APICommunications/Model/Foss/SW360Releases.cs +++ b/src/LCT.APICommunications/Model/Foss/SW360Releases.cs @@ -11,18 +11,29 @@ namespace LCT.APICommunications.Model.Foss /// /// SW360Releases Model /// - [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class SW360Releases { + #region Properties + /// + /// Gets or sets the release name. + /// [JsonProperty("name")] public string Name { get; set; } + /// + /// Gets or sets the release version. + /// [JsonProperty("version")] public string Version { get; set; } + /// + /// Gets or sets the links associated with the release. + /// [JsonProperty("_links")] public Links Links { get; set; } + + #endregion Properties } } \ No newline at end of file diff --git a/src/LCT.APICommunications/Model/Foss/Sw360AttachmentHash.cs b/src/LCT.APICommunications/Model/Foss/Sw360AttachmentHash.cs index c4e63f46f..de2899024 100644 --- a/src/LCT.APICommunications/Model/Foss/Sw360AttachmentHash.cs +++ b/src/LCT.APICommunications/Model/Foss/Sw360AttachmentHash.cs @@ -9,18 +9,36 @@ namespace LCT.APICommunications.Model.Foss /// /// The Sw360 AttachmentHash Model /// - - [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class Sw360AttachmentHash { + #region Properties + + /// + /// Gets or sets the attachment link. + /// public string AttachmentLink { get; set; } + /// + /// Gets or sets the hash code of the attachment. + /// public string HashCode { get; set; } + /// + /// Gets or sets the source download URL. + /// public string SourceDownloadUrl { get; set; } + /// + /// Gets or sets the SW360 attachment name. + /// public string SW360AttachmentName { get; set; } + + /// + /// Gets or sets a value indicating whether the attachment source is not available in SW360. + /// public bool isAttachmentSourcenotAvailableInSw360 { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/Foss/TriggerJobParams.cs b/src/LCT.APICommunications/Model/Foss/TriggerJobParams.cs index 6f79692c8..dc2a48bef 100644 --- a/src/LCT.APICommunications/Model/Foss/TriggerJobParams.cs +++ b/src/LCT.APICommunications/Model/Foss/TriggerJobParams.cs @@ -9,11 +9,21 @@ namespace LCT.APICommunications.Model.Foss /// /// The TriggerJob params model /// - [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class TriggerJobParams { + #region Properties + + /// + /// Gets or sets the folder identifier. + /// public string FolderId { get; set; } + + /// + /// Gets or sets the upload identifier. + /// public string UploadId { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/Foss/UploadComponentModel.cs b/src/LCT.APICommunications/Model/Foss/UploadComponentModel.cs index aee1c521d..fb074e4bd 100644 --- a/src/LCT.APICommunications/Model/Foss/UploadComponentModel.cs +++ b/src/LCT.APICommunications/Model/Foss/UploadComponentModel.cs @@ -11,17 +11,29 @@ namespace LCT.APICommunications.Model.Foss /// /// The UploadComponentModel /// - [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class UploadComponentModel { + #region Properties + + /// + /// Gets or sets the response code. + /// [JsonProperty("code")] public string Code { get; set; } + /// + /// Gets or sets the upload identifier. + /// [JsonProperty("message")] public string UploadId { get; set; } + /// + /// Gets or sets the response type. + /// [JsonProperty("type")] public string Type { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/Foss/UploadParams.cs b/src/LCT.APICommunications/Model/Foss/UploadParams.cs index ff1ba64aa..bf7ad56a5 100644 --- a/src/LCT.APICommunications/Model/Foss/UploadParams.cs +++ b/src/LCT.APICommunications/Model/Foss/UploadParams.cs @@ -9,14 +9,26 @@ namespace LCT.APICommunications.Model.Foss /// /// The fossology upload package params model /// - [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class UploadParams { + #region Properties + + /// + /// Gets or sets the folder identifier. + /// public string FolderId { get; set; } + /// + /// Gets or sets the upload description. + /// public string UploadDescription { get; set; } + /// + /// Gets or sets the public visibility setting. + /// public string Public { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/JfrogInfo.cs b/src/LCT.APICommunications/Model/JfrogInfo.cs index e438eec9b..4c19917de 100644 --- a/src/LCT.APICommunications/Model/JfrogInfo.cs +++ b/src/LCT.APICommunications/Model/JfrogInfo.cs @@ -5,16 +5,35 @@ // -------------------------------------------------------------------------------------------------------------------- using Newtonsoft.Json; + namespace LCT.APICommunications.Model { + /// + /// Represents JFrog Artifactory repository information. + /// [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class JfrogInfo { + #region Properties + + /// + /// Gets or sets the repository name. + /// [JsonProperty("repo")] public string Repo { get; set; } + + /// + /// Gets or sets the path within the repository. + /// [JsonProperty("path")] public string Path { get; set; } + + /// + /// Gets or sets the checksum information. + /// [JsonProperty("checksums")] public Checksum Checksum { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/LinkedReleases.cs b/src/LCT.APICommunications/Model/LinkedReleases.cs index 9631a0847..64f34012c 100644 --- a/src/LCT.APICommunications/Model/LinkedReleases.cs +++ b/src/LCT.APICommunications/Model/LinkedReleases.cs @@ -14,7 +14,14 @@ namespace LCT.APICommunications.Model [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class LinkedReleases { + #region Properties + + /// + /// Gets or sets the release identifier. + /// [JsonProperty("release")] public string Release { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/Links.cs b/src/LCT.APICommunications/Model/Links.cs index b4313934c..0e802f030 100644 --- a/src/LCT.APICommunications/Model/Links.cs +++ b/src/LCT.APICommunications/Model/Links.cs @@ -11,11 +11,17 @@ namespace LCT.APICommunications.Model /// /// The Link model /// - [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class Links { + #region Properties + + /// + /// Gets or sets the self-referencing link. + /// [JsonProperty("self")] public Self Self { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/PackageType.cs b/src/LCT.APICommunications/Model/PackageType.cs index a7329efca..a7109934b 100644 --- a/src/LCT.APICommunications/Model/PackageType.cs +++ b/src/LCT.APICommunications/Model/PackageType.cs @@ -6,11 +6,29 @@ namespace LCT.APICommunications.Model { + /// + /// Specifies the type of package. + /// public enum PackageType { + /// + /// Represents a cleared third-party package. + /// ClearedThirdParty, + + /// + /// Represents an internal package. + /// Internal, + + /// + /// Represents a development package. + /// Development, + + /// + /// Represents an unknown package type. + /// Unknown } } diff --git a/src/LCT.APICommunications/Model/ProjectEmbedded.cs b/src/LCT.APICommunications/Model/ProjectEmbedded.cs index 0d50fc287..c34edc1c7 100644 --- a/src/LCT.APICommunications/Model/ProjectEmbedded.cs +++ b/src/LCT.APICommunications/Model/ProjectEmbedded.cs @@ -4,7 +4,6 @@ // SPDX-License-Identifier: MIT // -------------------------------------------------------------------------------------------------------------------- - using Newtonsoft.Json; using System.Collections.Generic; @@ -13,11 +12,17 @@ namespace LCT.APICommunications.Model /// /// ProjectEmbeded json mapping model class /// - [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class ProjectEmbedded { + #region Properties + + /// + /// Gets or sets the list of SW360 projects. + /// [JsonProperty("sw360:projects")] public IList Sw360projects { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/ProjectReleases.cs b/src/LCT.APICommunications/Model/ProjectReleases.cs index 4f5043c1b..675b92e8f 100644 --- a/src/LCT.APICommunications/Model/ProjectReleases.cs +++ b/src/LCT.APICommunications/Model/ProjectReleases.cs @@ -12,27 +12,47 @@ namespace LCT.APICommunications.Model /// /// The ProjectRelease Model /// - /// - [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class ProjectReleases { + #region Properties + + /// + /// Gets or sets the project name. + /// [JsonProperty("name")] public string Name { get; set; } + /// + /// Gets or sets the version. + /// [JsonProperty("version")] public string Version { get; set; } + /// + /// Gets or sets the state. + /// [JsonProperty("state")] public string State { get; set; } + /// + /// Gets or sets the clearing state. + /// [JsonProperty("clearingState")] public string ClearingState { get; set; } + /// + /// Gets or sets the embedded release information. + /// [JsonProperty("_embedded")] public ReleaseEmbedded Embedded { get; set; } + /// + /// Gets or sets the list of linked releases. + /// [JsonProperty("linkedReleases")] public List LinkedReleases { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/ProjectsMapper.cs b/src/LCT.APICommunications/Model/ProjectsMapper.cs index a766a1dad..350ebaae1 100644 --- a/src/LCT.APICommunications/Model/ProjectsMapper.cs +++ b/src/LCT.APICommunications/Model/ProjectsMapper.cs @@ -14,7 +14,14 @@ namespace LCT.APICommunications.Model [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class ProjectsMapper { + #region Properties + + /// + /// Gets or sets the embedded project information. + /// [JsonProperty("_embedded")] public ProjectEmbedded Embedded { get; set; } + + #endregion Properties } } \ No newline at end of file diff --git a/src/LCT.APICommunications/Model/ReleaseAdditionalData.cs b/src/LCT.APICommunications/Model/ReleaseAdditionalData.cs index d0dcf0389..db76e725d 100644 --- a/src/LCT.APICommunications/Model/ReleaseAdditionalData.cs +++ b/src/LCT.APICommunications/Model/ReleaseAdditionalData.cs @@ -15,7 +15,14 @@ namespace LCT.APICommunications.Model [DataContract] public class ReleaseAdditionalData { + #region Properties + + /// + /// Gets or sets the FOSSology URL. + /// [DataMember(Name = "fossology url")] public string Fossology_url { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/ReleaseEmbedded.cs b/src/LCT.APICommunications/Model/ReleaseEmbedded.cs index ac0aa4804..f2b8540ba 100644 --- a/src/LCT.APICommunications/Model/ReleaseEmbedded.cs +++ b/src/LCT.APICommunications/Model/ReleaseEmbedded.cs @@ -12,12 +12,17 @@ namespace LCT.APICommunications.Model /// /// ReleaseEmbedded model /// - /// - [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class ReleaseEmbedded { + #region Properties + + /// + /// Gets or sets the list of SW360 releases. + /// [JsonProperty("sw360:releases")] public IList Sw360Releases { get; set; } + + #endregion Properties } } \ No newline at end of file diff --git a/src/LCT.APICommunications/Model/ReleaseIdOfComponent.cs b/src/LCT.APICommunications/Model/ReleaseIdOfComponent.cs index 9dbe4a438..797810024 100644 --- a/src/LCT.APICommunications/Model/ReleaseIdOfComponent.cs +++ b/src/LCT.APICommunications/Model/ReleaseIdOfComponent.cs @@ -12,60 +12,113 @@ namespace LCT.APICommunications.Model /// /// ReleaseIdOfComponent model /// - /// - [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class ReleaseIdOfComponent { + #region Properties + + /// + /// Gets or sets the component name. + /// [JsonProperty("name")] public string Name { get; set; } + /// + /// Gets or sets the description. + /// [JsonProperty("description")] public string Description { get; set; } + /// + /// Gets or sets the creation date. + /// [JsonProperty("createdOn")] public string CreatedOn { get; set; } + /// + /// Gets or sets the component type. + /// [JsonProperty("componentType")] public string ComponentType { get; set; } + /// + /// Gets or sets the component owner. + /// [JsonProperty("componentOwner")] public string ComponentOwner { get; set; } + /// + /// Gets or sets the owner accounting unit. + /// [JsonProperty("ownerAccountingUnit")] public string OwnerAccountingUnit { get; set; } + /// + /// Gets or sets the owner group. + /// [JsonProperty("ownerGroup")] public string OwnerGroup { get; set; } + /// + /// Gets or sets the owner country. + /// [JsonProperty("ownerCountry")] public string OwnerCountry { get; set; } + /// + /// Gets or sets the roles. + /// [JsonProperty("roles")] public Roles Roles { get; set; } + /// + /// Gets or sets the external identifiers. + /// [JsonProperty("externalIds")] public ExternalIds ExternalIds { get; set; } + /// + /// Gets or sets the list of categories. + /// [JsonProperty("categories")] public IList Categories { get; set; } + /// + /// Gets or sets the list of programming languages. + /// [JsonProperty("languages")] public IList Languages { get; set; } + /// + /// Gets or sets the list of operating systems. + /// [JsonProperty("operatingSystems")] public IList OperatingSystems { get; set; } + /// + /// Gets or sets the homepage URL. + /// [JsonProperty("homepage")] public string Homepage { get; set; } + /// + /// Gets or sets the mailing list. + /// [JsonProperty("_mailinglist")] public string Mailinglist { get; set; } + /// + /// Gets or sets the links. + /// [JsonProperty("_links")] public Links Links { get; set; } + /// + /// Gets or sets the embedded release information. + /// [JsonProperty("_embedded")] public ReleaseEmbedded Embedded { get; set; } + + #endregion Properties } } \ No newline at end of file diff --git a/src/LCT.APICommunications/Model/ReleaseLinked.cs b/src/LCT.APICommunications/Model/ReleaseLinked.cs index 6793b71af..c07a4c854 100644 --- a/src/LCT.APICommunications/Model/ReleaseLinked.cs +++ b/src/LCT.APICommunications/Model/ReleaseLinked.cs @@ -12,13 +12,33 @@ namespace LCT.APICommunications.Model [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class ReleaseLinked { + #region Properties + + /// + /// Gets or sets the release name. + /// public string Name { get; set; } = string.Empty; + /// + /// Gets or sets the version. + /// public string Version { get; set; } = string.Empty; + /// + /// Gets or sets the release identifier. + /// public string ReleaseId { get; set; } = string.Empty; + /// + /// Gets or sets the comment. + /// public string Comment { get; set; } = string.Empty; + + /// + /// Gets or sets the relation type. + /// public string Relation { get; set; } = string.Empty; + + #endregion Properties } } \ No newline at end of file diff --git a/src/LCT.APICommunications/Model/ReleaseLinks.cs b/src/LCT.APICommunications/Model/ReleaseLinks.cs index abba7209e..7eb40fbb7 100644 --- a/src/LCT.APICommunications/Model/ReleaseLinks.cs +++ b/src/LCT.APICommunications/Model/ReleaseLinks.cs @@ -14,10 +14,20 @@ namespace LCT.APICommunications.Model [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class ReleaseLinks { + #region Properties + + /// + /// Gets or sets the self-referencing link. + /// [JsonProperty("self")] public Self Self { get; set; } + /// + /// Gets or sets the SW360 component information. + /// [JsonProperty("sw360:component")] public Sw360Component Sw360Component { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/Releases.cs b/src/LCT.APICommunications/Model/Releases.cs index 612a1002f..8834b5088 100644 --- a/src/LCT.APICommunications/Model/Releases.cs +++ b/src/LCT.APICommunications/Model/Releases.cs @@ -14,32 +14,62 @@ namespace LCT.APICommunications.Model [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class Releases { + #region Properties + + /// + /// Gets or sets the release name. + /// [JsonProperty("name")] public string Name { get; set; } + /// + /// Gets or sets the version. + /// [JsonProperty("version")] public string Version { get; set; } + /// + /// Gets or sets the component identifier. + /// [JsonProperty("componentId")] public string ComponentId { get; set; } + /// + /// Gets or sets the source code download URL. + /// [JsonProperty("sourceCodeDownloadurl")] public string SourceDownloadurl { get; set; } + /// + /// Gets or sets the binary download URL. + /// [JsonProperty("binaryDownloadurl")] public string BinaryDownloadUrl { get; set; } + /// + /// Gets or sets the creation date. + /// [JsonProperty("createdOn")] public string CreatedOn { get; set; } + /// + /// Gets or sets the clearing state. + /// [JsonProperty("clearingState")] public string ClearingState { get; set; } + /// + /// Gets or sets the links. + /// [JsonProperty("_links")] public Links Links { get; set; } + /// + /// Gets or sets the external identifiers. + /// [JsonProperty("externalIds")] public ExternalIds ExternalIds { get; set; } + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/ReleasesDetails.cs b/src/LCT.APICommunications/Model/ReleasesDetails.cs index 093e7ece8..4e967e3a5 100644 --- a/src/LCT.APICommunications/Model/ReleasesDetails.cs +++ b/src/LCT.APICommunications/Model/ReleasesDetails.cs @@ -8,14 +8,32 @@ namespace LCT.APICommunications.Model { + /// + /// Represents detailed release information. + /// [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class ReleasesDetails { + #region Properties + + /// + /// Gets or sets the release name. + /// [JsonProperty("name")] public string Name { get; set; } + + /// + /// Gets or sets the version. + /// [JsonProperty("version")] public string Version { get; set; } + + /// + /// Gets or sets the embedded attachment information. + /// [JsonProperty("_embedded")] public AttachmentEmbedded Embedded { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/Releasestatus.cs b/src/LCT.APICommunications/Model/Releasestatus.cs index 1fe5a5747..798ad65fe 100644 --- a/src/LCT.APICommunications/Model/Releasestatus.cs +++ b/src/LCT.APICommunications/Model/Releasestatus.cs @@ -6,10 +6,24 @@ namespace LCT.APICommunications.Model { + /// + /// Represents the release status information. + /// [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class Releasestatus { + #region Properties + + /// + /// Gets or sets the SW360 releases information. + /// public Sw360Releases sw360Releases { get; set; } + + /// + /// Gets or sets a value indicating whether the release exists. + /// public bool isReleaseExist { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/Self.cs b/src/LCT.APICommunications/Model/Self.cs index 91a6a4638..bf60c24d8 100644 --- a/src/LCT.APICommunications/Model/Self.cs +++ b/src/LCT.APICommunications/Model/Self.cs @@ -11,12 +11,17 @@ namespace LCT.APICommunications.Model /// /// The Self model class /// - /// - [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class Self { + #region Properties + + /// + /// Gets or sets the hyperlink reference. + /// [JsonProperty("href")] public string Href { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/Sw360AllProjects.cs b/src/LCT.APICommunications/Model/Sw360AllProjects.cs index d8e904fbc..62da3fc95 100644 --- a/src/LCT.APICommunications/Model/Sw360AllProjects.cs +++ b/src/LCT.APICommunications/Model/Sw360AllProjects.cs @@ -15,27 +15,50 @@ namespace LCT.APICommunications.Model [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class Sw360AllProjects { + #region Properties + + /// + /// Gets or sets the project name. + /// [JsonProperty("name")] public string Name { get; set; } + /// + /// Gets or sets the version. + /// [JsonProperty("version")] public string Version { get; set; } + /// + /// Gets or sets the tag. + /// [JsonProperty("tag")] public string Tag { get; set; } + /// + /// Gets or sets the clearing state. + /// [JsonProperty("clearingState")] public string ClearingState { get; set; } + /// + /// Gets or sets the state. + /// [JsonProperty("state")] public string State { get; set; } + /// + /// Gets or sets the links. + /// [JsonProperty("_links")] public Links Links { get; set; } + /// + /// Gets or sets the list of linked releases. + /// [JsonProperty("linkedReleases")] public IList LinkedReleases { get; set; } + #endregion Properties } - } diff --git a/src/LCT.APICommunications/Model/Sw360Attachments.cs b/src/LCT.APICommunications/Model/Sw360Attachments.cs index 69e2d2659..6f8e29874 100644 --- a/src/LCT.APICommunications/Model/Sw360Attachments.cs +++ b/src/LCT.APICommunications/Model/Sw360Attachments.cs @@ -14,16 +14,32 @@ namespace LCT.APICommunications.Model [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class Sw360Attachments { + #region Properties + + /// + /// Gets or sets the filename. + /// [JsonProperty("filename")] public string Filename { get; set; } + /// + /// Gets or sets the SHA1 hash. + /// [JsonProperty("sha1")] public string Sha1 { get; set; } + /// + /// Gets or sets the attachment type. + /// [JsonProperty("attachmentType")] public string AttachmentType { get; set; } + /// + /// Gets or sets the attachment links. + /// [JsonProperty("_links")] public AttachmentLinks Links { get; set; } + + #endregion Properties } } \ No newline at end of file diff --git a/src/LCT.APICommunications/Model/Sw360Component.cs b/src/LCT.APICommunications/Model/Sw360Component.cs index 6431ac904..2a56e807b 100644 --- a/src/LCT.APICommunications/Model/Sw360Component.cs +++ b/src/LCT.APICommunications/Model/Sw360Component.cs @@ -14,7 +14,14 @@ namespace LCT.APICommunications.Model [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class Sw360Component { + #region Properties + + /// + /// Gets or sets the hyperlink reference. + /// [JsonProperty("href")] public string Href { get; set; } + + #endregion Properties } } \ No newline at end of file diff --git a/src/LCT.APICommunications/Model/Sw360Components.cs b/src/LCT.APICommunications/Model/Sw360Components.cs index 2acaf45d9..540c98bbe 100644 --- a/src/LCT.APICommunications/Model/Sw360Components.cs +++ b/src/LCT.APICommunications/Model/Sw360Components.cs @@ -14,16 +14,32 @@ namespace LCT.APICommunications.Model [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class Sw360Components { + #region Properties + + /// + /// Gets or sets the component name. + /// [JsonProperty("name")] public string Name { get; set; } + /// + /// Gets or sets the component type. + /// [JsonProperty("componentType")] public string ComponentType { get; set; } + /// + /// Gets or sets the links. + /// [JsonProperty("_links")] public Links Links { get; set; } + /// + /// Gets or sets the external identifiers. + /// [JsonProperty("externalIds")] public ExternalIds ExternalIds { get; set; } + + #endregion Properties } } \ No newline at end of file diff --git a/src/LCT.APICommunications/Model/Sw360Href.cs b/src/LCT.APICommunications/Model/Sw360Href.cs index 9b9fade5a..91d139414 100644 --- a/src/LCT.APICommunications/Model/Sw360Href.cs +++ b/src/LCT.APICommunications/Model/Sw360Href.cs @@ -14,7 +14,14 @@ namespace LCT.APICommunications.Model [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class Sw360Href { + #region Properties + + /// + /// Gets or sets the hyperlink reference. + /// [JsonProperty("href")] public string Href { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/Sw360LinkedRelease.cs b/src/LCT.APICommunications/Model/Sw360LinkedRelease.cs index 2ec3eed82..ae6e7953f 100644 --- a/src/LCT.APICommunications/Model/Sw360LinkedRelease.cs +++ b/src/LCT.APICommunications/Model/Sw360LinkedRelease.cs @@ -14,22 +14,44 @@ namespace LCT.APICommunications.Model [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class Sw360LinkedRelease { + #region Properties + + /// + /// Gets or sets the creator. + /// [JsonProperty("createdBy")] public string CreatedBy { get; set; } + /// + /// Gets or sets the release identifier. + /// [JsonProperty("release")] public string Release { get; set; } + /// + /// Gets or sets the mainline state. + /// [JsonProperty("mainlineState")] public string MainlineState { get; set; } + /// + /// Gets or sets the comment. + /// [JsonProperty("comment")] public string Comment { get; set; } + /// + /// Gets or sets the creation date. + /// [JsonProperty("createdOn")] public string CreatedOn { get; set; } + /// + /// Gets or sets the relation type. + /// [JsonProperty("relation")] public string Relation { get; set; } + + #endregion Properties } } \ No newline at end of file diff --git a/src/LCT.APICommunications/Model/Sw360Projects.cs b/src/LCT.APICommunications/Model/Sw360Projects.cs index 430286638..cf982cfd4 100644 --- a/src/LCT.APICommunications/Model/Sw360Projects.cs +++ b/src/LCT.APICommunications/Model/Sw360Projects.cs @@ -15,22 +15,44 @@ namespace LCT.APICommunications.Model [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class Sw360Projects { + #region Properties + + /// + /// Gets or sets the project name. + /// [JsonProperty("name")] public string Name { get; set; } + /// + /// Gets or sets the version. + /// [JsonProperty("version")] public string Version { get; set; } + /// + /// Gets or sets the list of security responsibles. + /// [JsonProperty("securityResponsibles")] public IList SecurityResponsibles { get; set; } + /// + /// Gets or sets the project type. + /// [JsonProperty("projectType")] public string ProjectType { get; set; } + /// + /// Gets or sets the visibility. + /// [JsonProperty("visibility")] public string Visibility { get; set; } + /// + /// Gets or sets the links. + /// [JsonProperty("_links")] public Links Links { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/Sw360Releases.cs b/src/LCT.APICommunications/Model/Sw360Releases.cs index bfe252988..e1248069a 100644 --- a/src/LCT.APICommunications/Model/Sw360Releases.cs +++ b/src/LCT.APICommunications/Model/Sw360Releases.cs @@ -14,16 +14,32 @@ namespace LCT.APICommunications.Model [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class Sw360Releases { + #region Properties + + /// + /// Gets or sets the release name. + /// [JsonProperty("name")] public string Name { get; set; } + /// + /// Gets or sets the version. + /// [JsonProperty("version")] public string Version { get; set; } + /// + /// Gets or sets the external identifiers. + /// [JsonProperty("externalIds")] public ExternalIds ExternalIds { get; set; } + /// + /// Gets or sets the links. + /// [JsonProperty("_links")] public Links Links { get; set; } + + #endregion Properties } } \ No newline at end of file diff --git a/src/LCT.APICommunications/Model/UpdateLinkedRelease.cs b/src/LCT.APICommunications/Model/UpdateLinkedRelease.cs index 5c7480bcf..cc5b8781b 100644 --- a/src/LCT.APICommunications/Model/UpdateLinkedRelease.cs +++ b/src/LCT.APICommunications/Model/UpdateLinkedRelease.cs @@ -8,11 +8,20 @@ namespace LCT.APICommunications.Model { - + /// + /// Represents a request to update a linked release. + /// [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class UpdateLinkedRelease { + #region Properties + + /// + /// Gets or sets the comment for the linked release update. + /// [JsonProperty("comment")] public string Comment { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/UpdateRelease.cs b/src/LCT.APICommunications/Model/UpdateRelease.cs index 444b21b0c..23955ab61 100644 --- a/src/LCT.APICommunications/Model/UpdateRelease.cs +++ b/src/LCT.APICommunications/Model/UpdateRelease.cs @@ -11,11 +11,17 @@ namespace LCT.APICommunications.Model /// /// The UpdateRelease model /// - [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class UpdateRelease { + #region Properties + + /// + /// Gets or sets the clearing state. + /// [JsonProperty("clearingState")] public string ClearingState { get; set; } = string.Empty; + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/UpdateReleaseAdditinoalData.cs b/src/LCT.APICommunications/Model/UpdateReleaseAdditinoalData.cs index e675d1896..a58c08433 100644 --- a/src/LCT.APICommunications/Model/UpdateReleaseAdditinoalData.cs +++ b/src/LCT.APICommunications/Model/UpdateReleaseAdditinoalData.cs @@ -9,11 +9,20 @@ namespace LCT.APICommunications.Model { - + /// + /// Represents a request to update release additional data. + /// [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class UpdateReleaseAdditinoalData { + #region Properties + + /// + /// Gets or sets the additional data dictionary. + /// [JsonProperty("additionalData")] public Dictionary AdditionalData { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/UpdateReleaseExternalId.cs b/src/LCT.APICommunications/Model/UpdateReleaseExternalId.cs index 8af00d78b..aeeb5b476 100644 --- a/src/LCT.APICommunications/Model/UpdateReleaseExternalId.cs +++ b/src/LCT.APICommunications/Model/UpdateReleaseExternalId.cs @@ -9,10 +9,20 @@ namespace LCT.APICommunications.Model { + /// + /// Represents a request to update release external identifiers. + /// [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class UpdateReleaseExternalId { + #region Properties + + /// + /// Gets or sets the external identifiers dictionary. + /// [JsonProperty("externalIds")] public Dictionary ExternalIds { get; set; } = new Dictionary(); + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/UploadArgs.cs b/src/LCT.APICommunications/Model/UploadArgs.cs index f9e22f46d..887635aeb 100644 --- a/src/LCT.APICommunications/Model/UploadArgs.cs +++ b/src/LCT.APICommunications/Model/UploadArgs.cs @@ -6,11 +6,29 @@ namespace LCT.APICommunications.Model { + /// + /// Represents arguments for upload operations. + /// [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class UploadArgs { + #region Properties + + /// + /// Gets or sets the package name. + /// public string PackageName { get; set; } + + /// + /// Gets or sets the release name. + /// public string ReleaseName { get; set; } + + /// + /// Gets or sets the version. + /// public string Version { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/Model/UploadInfo.cs b/src/LCT.APICommunications/Model/UploadInfo.cs index 97fc181c0..8c2c5ffe5 100644 --- a/src/LCT.APICommunications/Model/UploadInfo.cs +++ b/src/LCT.APICommunications/Model/UploadInfo.cs @@ -6,12 +6,29 @@ namespace LCD.Common.Models { - + /// + /// Represents upload information. + /// [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class UploadInfo { + #region Properties + + /// + /// Gets or sets the upload identifier. + /// public string uploadId { get; set; } + + /// + /// Gets or sets the folder identifier. + /// public string folderId { get; set; } + + /// + /// Gets or sets the user identifier. + /// public string userId { get; set; } + + #endregion Properties } } diff --git a/src/LCT.APICommunications/NpmJfrogAPICommunication.cs b/src/LCT.APICommunications/NpmJfrogAPICommunication.cs index 872f41e89..be115fde3 100644 --- a/src/LCT.APICommunications/NpmJfrogAPICommunication.cs +++ b/src/LCT.APICommunications/NpmJfrogAPICommunication.cs @@ -15,16 +15,57 @@ namespace LCT.APICommunications { + /// + /// Provides NPM-specific JFrog Artifactory API communication operations. + /// public class NpmJfrogApiCommunication : JfrogApicommunication { + #region Fields + + /// + /// Logger instance for this class. + /// static readonly ILog Logger = LoggerFactory.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private static int TimeoutInSec { get; set; } + + /// + /// Environment helper instance for exit handling. + /// private static readonly EnvironmentHelper environmentHelper = new EnvironmentHelper(); + + #endregion + + #region Properties + + /// + /// Gets or sets the timeout in seconds for HTTP requests. + /// + private static int TimeoutInSec { get; set; } + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + /// The repository domain name. + /// The source repository name. + /// The repository credentials. + /// The timeout in seconds. public NpmJfrogApiCommunication(string repoDomainName, string srcrepoName, ArtifactoryCredentials repoCredentials, int timeout) : base(repoDomainName, srcrepoName, repoCredentials, timeout) { TimeoutInSec = timeout; } + #endregion + + #region Methods + + /// + /// Creates and configures an HTTP client with authentication. + /// + /// The artifactory credentials. + /// A configured HTTP client instance. private static HttpClient GetHttpClient(ArtifactoryCredentials credentials) { var handler = new RetryHttpClientHandler() @@ -38,6 +79,10 @@ private static HttpClient GetHttpClient(ArtifactoryCredentials credentials) return httpClient; } + /// + /// Asynchronously retrieves the API key from Artifactory. + /// + /// An HTTP response message containing the API key. public override async Task GetApiKey() { HttpClient httpClient = GetHttpClient(ArtifactoryCredentials); @@ -45,6 +90,11 @@ public override async Task GetApiKey() return await httpClient.GetAsync(url); } + /// + /// Asynchronously copies a component from a remote repository. + /// + /// The component to copy. + /// An HTTP response message indicating the result of the copy operation. public override async Task CopyFromRemoteRepo(ComponentsToArtifactory component) { HttpClient httpClient = GetHttpClient(ArtifactoryCredentials); @@ -53,6 +103,11 @@ public override async Task CopyFromRemoteRepo(ComponentsToA return await httpClient.PostAsync(component.CopyPackageApiUrl, httpContent); } + /// + /// Asynchronously moves a component from one repository to another. + /// + /// The component to move. + /// An HTTP response message indicating the result of the move operation. public override async Task MoveFromRepo(ComponentsToArtifactory component) { HttpClient httpClient = GetHttpClient(ArtifactoryCredentials); @@ -61,6 +116,11 @@ public override async Task MoveFromRepo(ComponentsToArtifac return await httpClient.PostAsync(component.MovePackageApiUrl, httpContent); } + /// + /// Asynchronously retrieves package information from Artifactory. + /// + /// The component to retrieve information for. + /// An HTTP response message containing the package information. public override async Task GetPackageInfo(ComponentsToArtifactory component) { HttpResponseMessage responseMessage = new HttpResponseMessage(); @@ -80,6 +140,12 @@ public override async Task GetPackageInfo(ComponentsToArtif return result; } + /// + /// Updates the package properties in JFrog Artifactory with the SW360 release URL. + /// + /// The SW360 release URL. + /// The destination repository name. + /// The upload arguments containing package information. public override void UpdatePackagePropertiesInJfrog(string sw360releaseUrl, string destRepoName, UploadArgs uploadArgs) { HttpClient httpClient = GetHttpClient(ArtifactoryCredentials); @@ -88,5 +154,7 @@ public override void UpdatePackagePropertiesInJfrog(string sw360releaseUrl, stri $"properties=sw360url={sw360releaseUrl}"; httpClient.PutAsync(url, httpContent); } + + #endregion } -} +} \ No newline at end of file diff --git a/src/LCT.APICommunications/NugetJfrogAPICommunication.cs b/src/LCT.APICommunications/NugetJfrogAPICommunication.cs index 7e63fbeed..d155a9717 100644 --- a/src/LCT.APICommunications/NugetJfrogAPICommunication.cs +++ b/src/LCT.APICommunications/NugetJfrogAPICommunication.cs @@ -15,16 +15,57 @@ namespace LCT.APICommunications { + /// + /// Provides NuGet-specific JFrog Artifactory API communication operations. + /// public class NugetJfrogApiCommunication : JfrogApicommunication { - private static int TimeoutInSec { get; set; } + #region Fields + + /// + /// Logger instance for this class. + /// static readonly ILog Logger = LoggerFactory.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// Environment helper instance for exit handling. + /// private static readonly EnvironmentHelper environmentHelper = new EnvironmentHelper(); + + #endregion + + #region Properties + + /// + /// Gets or sets the timeout in seconds for HTTP requests. + /// + private static int TimeoutInSec { get; set; } + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + /// The repository domain name. + /// The source repository name. + /// The repository credentials. + /// The timeout in seconds. public NugetJfrogApiCommunication(string repoDomainName, string srcrepoName, ArtifactoryCredentials repoCredentials, int timeout) : base(repoDomainName, srcrepoName, repoCredentials, timeout) { TimeoutInSec = timeout; } + #endregion + + #region Methods + + /// + /// Creates and configures an HTTP client with authentication. + /// + /// The artifactory credentials. + /// A configured HTTP client instance. private static HttpClient GetHttpClient(ArtifactoryCredentials credentials) { var handler = new RetryHttpClientHandler() @@ -38,6 +79,10 @@ private static HttpClient GetHttpClient(ArtifactoryCredentials credentials) return httpClient; } + /// + /// Asynchronously retrieves the API key from Artifactory. + /// + /// An HTTP response message containing the API key. public override async Task GetApiKey() { HttpClient httpClient = GetHttpClient(ArtifactoryCredentials); @@ -45,6 +90,11 @@ public override async Task GetApiKey() return await httpClient.GetAsync(url); } + /// + /// Asynchronously copies a component from a remote repository. + /// + /// The component to copy. + /// An HTTP response message indicating the result of the copy operation. public override async Task CopyFromRemoteRepo(ComponentsToArtifactory component) { HttpClient httpClient = GetHttpClient(ArtifactoryCredentials); @@ -53,6 +103,11 @@ public override async Task CopyFromRemoteRepo(ComponentsToA return await httpClient.PostAsync(component.CopyPackageApiUrl, httpContent); } + /// + /// Asynchronously moves a component from one repository to another. + /// + /// The component to move. + /// An HTTP response message indicating the result of the move operation. public override async Task MoveFromRepo(ComponentsToArtifactory component) { HttpClient httpClient = GetHttpClient(ArtifactoryCredentials); @@ -61,6 +116,11 @@ public override async Task MoveFromRepo(ComponentsToArtifac return await httpClient.PostAsync(component.MovePackageApiUrl, httpContent); } + /// + /// Asynchronously retrieves package information from Artifactory. + /// + /// The component to retrieve information for. + /// An HTTP response message containing the package information. public override async Task GetPackageInfo(ComponentsToArtifactory component) { HttpResponseMessage responseMessage = new HttpResponseMessage(); @@ -81,6 +141,12 @@ public override async Task GetPackageInfo(ComponentsToArtif return result; } + /// + /// Updates the package properties in JFrog Artifactory with the SW360 release URL. + /// + /// The SW360 release URL. + /// The destination repository name. + /// The upload arguments containing package information. public override void UpdatePackagePropertiesInJfrog(string sw360releaseUrl, string destRepoName, UploadArgs uploadArgs) { HttpClient httpClient = GetHttpClient(ArtifactoryCredentials); @@ -90,5 +156,6 @@ public override void UpdatePackagePropertiesInJfrog(string sw360releaseUrl, stri httpClient.PutAsync(url, httpContent); } + #endregion } -} +} \ No newline at end of file diff --git a/src/LCT.APICommunications/PythonJfrogAPICommunication.cs b/src/LCT.APICommunications/PythonJfrogAPICommunication.cs index 5c24442d9..9cf5c35a0 100644 --- a/src/LCT.APICommunications/PythonJfrogAPICommunication.cs +++ b/src/LCT.APICommunications/PythonJfrogAPICommunication.cs @@ -16,11 +16,33 @@ namespace LCT.APICommunications { public class PythonJfrogApiCommunication : JfrogApicommunication { + #region Properties + /// + /// Gets or sets the timeout duration in seconds for HTTP requests. + /// private static int TimeoutInSec { get; set; } + #endregion + + #region Constructors + /// + /// Initializes a new instance of the class. + /// + /// The repository domain name. + /// The source repository name. + /// The artifactory credentials. + /// The timeout duration in seconds. public PythonJfrogApiCommunication(string repoDomainName, string srcrepoName, ArtifactoryCredentials repoCredentials, int timeout) : base(repoDomainName, srcrepoName, repoCredentials, timeout) { TimeoutInSec = timeout; } + #endregion + + #region Methods + /// + /// Gets a configured HTTP client with authentication headers. + /// + /// The artifactory credentials. + /// A configured HTTP client instance. private static HttpClient GetHttpClient(ArtifactoryCredentials credentials) { var handler = new RetryHttpClientHandler() @@ -34,43 +56,62 @@ private static HttpClient GetHttpClient(ArtifactoryCredentials credentials) return httpClient; } + /// + /// Asynchronously retrieves the API key from the Artifactory server. + /// + /// An HTTP response message containing the API key information. public override async Task GetApiKey() { - HttpClient httpClient = GetHttpClient(ArtifactoryCredentials); string url = $"{DomainName}/api/security/apiKey"; - return await httpClient.GetAsync(url); + return await GetHttpClient(ArtifactoryCredentials).GetAsync(url); } + /// + /// Asynchronously copies a package from the remote repository. + /// + /// The component to copy to Artifactory. + /// An HTTP response message indicating the result of the copy operation. public override async Task CopyFromRemoteRepo(ComponentsToArtifactory component) { HttpClient httpClient = GetHttpClient(ArtifactoryCredentials); - const HttpContent httpContent = null; - await LogHandlingHelper.HttpRequestHandling("Package copy from remote repository", $"MethodName:CopyFromRemoteRepo()", httpClient, component.CopyPackageApiUrl, httpContent); - return await httpClient.PostAsync(component.CopyPackageApiUrl, httpContent); + await LogHandlingHelper.HttpRequestHandling("Package copy from remote repository", $"MethodName:CopyFromRemoteRepo()", httpClient, component.CopyPackageApiUrl, null); + return await httpClient.PostAsync(component.CopyPackageApiUrl, null); } + /// + /// Asynchronously moves a package from the remote repository. + /// + /// The component to move in Artifactory. + /// An HTTP response message indicating the result of the move operation. public override async Task MoveFromRepo(ComponentsToArtifactory component) { HttpClient httpClient = GetHttpClient(ArtifactoryCredentials); - const HttpContent httpContent = null; - await LogHandlingHelper.HttpRequestHandling("Package Move from remote repository", $"MethodName:MoveFromRepo()", httpClient, component.MovePackageApiUrl, httpContent); - return await httpClient.PostAsync(component.MovePackageApiUrl, httpContent); + await LogHandlingHelper.HttpRequestHandling("Package Move from remote repository", $"MethodName:MoveFromRepo()", httpClient, component.MovePackageApiUrl, null); + return await httpClient.PostAsync(component.MovePackageApiUrl, null); } + /// + /// Asynchronously retrieves package information from Artifactory. + /// + /// The component to retrieve information for. + /// An HTTP response message containing the package information. public override async Task GetPackageInfo(ComponentsToArtifactory component) { - HttpClient httpClient = GetHttpClient(ArtifactoryCredentials); - return await httpClient.GetAsync(component.PackageInfoApiUrl); + return await GetHttpClient(ArtifactoryCredentials).GetAsync(component.PackageInfoApiUrl); } + + /// + /// Updates package properties in JFrog Artifactory with SW360 release URL. + /// + /// The SW360 release URL. + /// The destination repository name. + /// The upload arguments containing release information. public override void UpdatePackagePropertiesInJfrog(string sw360releaseUrl, string destRepoName, UploadArgs uploadArgs) { - HttpClient httpClient = GetHttpClient(ArtifactoryCredentials); - const HttpContent httpContent = null; string url = $"{DomainName}/api/storage/{destRepoName}/{uploadArgs.ReleaseName}.{uploadArgs.Version}.pypi?" + $"properties=sw360url={sw360releaseUrl}"; - httpClient.PutAsync(url, httpContent); + GetHttpClient(ArtifactoryCredentials).PutAsync(url, null); } + #endregion } -} - - +} \ No newline at end of file diff --git a/src/LCT.APICommunications/RetryHttpClientHandler.cs b/src/LCT.APICommunications/RetryHttpClientHandler.cs index 389c53c42..43c8bdaf5 100644 --- a/src/LCT.APICommunications/RetryHttpClientHandler.cs +++ b/src/LCT.APICommunications/RetryHttpClientHandler.cs @@ -15,11 +15,35 @@ namespace LCT.APICommunications { + /// + /// A delegating handler that implements retry logic for HTTP requests using Polly policies. + /// public class RetryHttpClientHandler : DelegatingHandler { + #region Fields + + /// + /// The asynchronous retry policy for handling transient HTTP failures. + /// private readonly AsyncPolicy _retryPolicy; + + /// + /// The logger instance for logging retry attempts and related information. + /// static readonly ILog Logger = LoggerFactory.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// Flag indicating whether the initial retry has been logged. + /// private bool _initialRetryLogged = false; + + #endregion Fields + + #region Constructors + + /// + /// Initializes a new instance of the class with a default retry policy. + /// public RetryHttpClientHandler() { // Define the retry policy (retry on 5xx, 408, and transient errors) @@ -38,6 +62,17 @@ public RetryHttpClientHandler() OnRetry); } + #endregion Constructors + + #region Methods + + /// + /// Handles the retry callback when a retry attempt occurs. + /// + /// The result of the failed request attempt. + /// The time span to wait before the next retry. + /// The current retry attempt number. + /// The context containing request metadata. private void OnRetry(DelegateResult outcome, TimeSpan timespan, int attempt, Context context) { var httpMethod = context.ContainsKey("HttpMethod") ? context["HttpMethod"] : "Unknown Method"; @@ -55,6 +90,13 @@ private void OnRetry(DelegateResult outcome, TimeSpan times context["RetryAttempt"] = attempt; _initialRetryLogged = true; } + + /// + /// Asynchronously sends an HTTP request with retry logic applied. + /// + /// The HTTP request message to send. + /// A cancellation token to cancel the operation. + /// An HttpResponseMessage representing the response from the server. protected override async Task SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) { var context = new Context @@ -79,6 +121,12 @@ protected override async Task SendAsync(HttpRequestMessage return response; } + + /// + /// Asynchronously executes an action with retry logic for handling WebException failures. + /// + /// The asynchronous action to execute with retry support. + /// A Task representing the asynchronous operation. public static async Task ExecuteWithRetryAsync(Func action) { var retryPolicy = Policy @@ -92,6 +140,12 @@ public static async Task ExecuteWithRetryAsync(Func action) await retryPolicy.ExecuteAsync(action); } + + /// + /// Gets the retry interval for a given attempt number. + /// + /// The current retry attempt number. + /// A TimeSpan representing the wait duration before the next retry. private static TimeSpan GetRetryInterval(int attempt) { if (attempt >= 1 && attempt <= ApiConstant.APIRetryIntervals.Count) @@ -99,5 +153,6 @@ private static TimeSpan GetRetryInterval(int attempt) return TimeSpan.Zero; // Default if out of range } + #endregion Methods } } diff --git a/src/LCT.APICommunications/SW360Apicommunication.cs b/src/LCT.APICommunications/SW360Apicommunication.cs index fc4c381a4..e79220152 100644 --- a/src/LCT.APICommunications/SW360Apicommunication.cs +++ b/src/LCT.APICommunications/SW360Apicommunication.cs @@ -21,8 +21,17 @@ namespace LCT.APICommunications { + /// + /// Provides extension methods for HttpClient. + /// public static class HttpClientExtensions { + /// + /// Sets log warning headers on the HttpClient for diagnostic purposes. + /// + /// The HttpClient instance to configure. + /// Indicates whether warnings should be logged. + /// Additional URL information for logging context. public static void SetLogWarnings(this HttpClient client, bool logWarnings, string urlInformation) { client.DefaultRequestHeaders.Remove("LogWarnings"); @@ -37,7 +46,7 @@ public static void SetLogWarnings(this HttpClient client, bool logWarnings, stri /// public class SW360Apicommunication(SW360ConnectionSettings sw360ConnectionSettings) : ISw360ApiCommunication { - #region VARIABLE DECLARATION + #region Fields private readonly string sw360AuthTokenType = sw360ConnectionSettings.SW360AuthTokenType; private readonly string sw360AuthToken = sw360ConnectionSettings.Sw360Token; private readonly string sw360ComponentApi = $"{sw360ConnectionSettings.SW360URL}{ApiConstant.Sw360ComponentApiSuffix}"; @@ -54,9 +63,13 @@ public class SW360Apicommunication(SW360ConnectionSettings sw360ConnectionSettin private const string GetReleasesMessage = "Get Releases"; private const string TriggerFossologyMessage = "Trigger Fossology Process"; #endregion - #region PUBLIC METHODS + #region Methods + /// + /// Asynchronously retrieves all projects from SW360. + /// + /// A JSON string containing the project data. public async Task GetProjects() { HttpClient httpClient = GetHttpClient(); @@ -75,6 +88,10 @@ public async Task GetProjects() return result; } + /// + /// Asynchronously retrieves all SW360 users. + /// + /// A JSON string containing the SW360 users data. public async Task GetSw360Users() { HttpClient httpClient = GetHttpClient(); @@ -82,6 +99,11 @@ public async Task GetSw360Users() return await httpClient.GetStringAsync(sw360UsersApi); } + /// + /// Asynchronously retrieves projects by their name from SW360. + /// + /// The name of the project to search for. + /// A JSON string containing the matching project data. public async Task GetProjectsByName(string projectName) { HttpClient httpClient = GetHttpClient(); @@ -90,6 +112,11 @@ public async Task GetProjectsByName(string projectName) return await httpClient.GetStringAsync(projectNameApiUrl); } + /// + /// Asynchronously retrieves projects by their tag from SW360. + /// + /// The tag to filter projects by. + /// An HttpResponseMessage containing the matching project data. public async Task GetProjectsByTag(string projectTag) { HttpClient httpClient = GetHttpClient(); @@ -98,6 +125,11 @@ public async Task GetProjectsByTag(string projectTag) return await httpClient.GetAsync(projectsByTagUrl); } + /// + /// Asynchronously retrieves a project by its unique identifier from SW360. + /// + /// The unique identifier of the project. + /// An HttpResponseMessage containing the project data. public async Task GetProjectById(string projectId) { HttpClient httpClient = GetHttpClient(); @@ -128,6 +160,10 @@ public async Task GetProjectById(string projectId) return result; } + /// + /// Asynchronously retrieves all releases from SW360. + /// + /// A JSON string containing the release data. public async Task GetReleases() { HttpClient httpClient = GetHttpClient(); @@ -174,6 +210,13 @@ public async Task GetReleases() } return result; } + + /// + /// Asynchronously triggers the Fossology scanning process for a release. + /// + /// The unique identifier of the release. + /// The SW360 link for the Fossology process. + /// A JSON string containing the Fossology process response. public async Task TriggerFossologyProcess(string releaseId, string sw360link) { HttpClient httpClient = GetHttpClient(); @@ -200,6 +243,12 @@ public async Task TriggerFossologyProcess(string releaseId, string sw360 throw; } } + + /// + /// Asynchronously checks the status of a Fossology scanning process. + /// + /// The link to check the Fossology process status. + /// An HttpResponseMessage containing the process status. public async Task CheckFossologyProcessStatus(string link) { HttpClient httpClient = GetHttpClient(); @@ -207,6 +256,11 @@ public async Task CheckFossologyProcessStatus(string link) await LogHandlingHelper.HttpRequestHandling(TriggerFossologyMessage, $"MethodName:TriggerFossologyProcess()", httpClient, link); return await httpClient.GetAsync(link); } + + /// + /// Asynchronously retrieves all components from SW360. + /// + /// A JSON string containing the component data. public async Task GetComponents() { HttpClient httpClient = GetHttpClient(); @@ -215,6 +269,12 @@ public async Task GetComponents() return await httpClient.GetStringAsync(sw360ComponentApi); } + /// + /// Asynchronously retrieves a release by its external identifier. + /// + /// The Package URL identifier. + /// The external identifier key prefix. + /// An HttpResponseMessage containing the release data. public async Task GetReleaseByExternalId(string purlId, string externalIdKey = "") { HttpClient httpClient = GetHttpClient(); @@ -224,6 +284,12 @@ public async Task GetReleaseByExternalId(string purlId, str return await httpClient.GetAsync(releaseByExternalIdUrl); } + /// + /// Asynchronously retrieves a component by its external identifier. + /// + /// The Package URL identifier. + /// The external identifier key prefix. + /// An HttpResponseMessage containing the component data. public async Task GetComponentByExternalId(string purlId, string externalIdKey = "") { HttpClient httpClient = GetHttpClient(); @@ -233,6 +299,11 @@ public async Task GetComponentByExternalId(string purlId, s return await httpClient.GetAsync(componentByExternalIdUrl); } + /// + /// Asynchronously retrieves a release by its unique identifier. + /// + /// The unique identifier of the release. + /// An HttpResponseMessage containing the release data. public async Task GetReleaseById(string releaseId) { HttpClient httpClient = GetHttpClient(); @@ -242,6 +313,11 @@ public async Task GetReleaseById(string releaseId) return await httpClient.GetAsync(url); } + /// + /// Asynchronously retrieves a release by its link URL. + /// + /// The link URL of the release. + /// An HttpResponseMessage containing the release data. public async Task GetReleaseByLink(string releaseLink) { HttpClient httpClient = GetHttpClient(); @@ -249,6 +325,12 @@ public async Task GetReleaseByLink(string releaseLink) return await httpClient.GetAsync(releaseLink); } + /// + /// Asynchronously links releases to a specified SW360 project. + /// + /// The HTTP content containing the release link data. + /// The unique identifier of the SW360 project. + /// An HttpResponseMessage indicating the result of the link operation. public async Task LinkReleasesToProject(HttpContent httpContent, string sw360ProjectId) { HttpClient httpClient = GetHttpClient(); @@ -258,6 +340,13 @@ public async Task LinkReleasesToProject(HttpContent httpCon return await httpClient.PostAsync(url, httpContent); } + /// + /// Asynchronously updates a linked release within a project. + /// + /// The unique identifier of the project. + /// The unique identifier of the release to update. + /// The update data for the linked release. + /// An HttpResponseMessage indicating the result of the update operation. public async Task UpdateLinkedRelease(string projectId, string releaseId, UpdateLinkedRelease updateLinkedRelease) { HttpClient httpClient = GetHttpClient(); @@ -269,6 +358,11 @@ public async Task UpdateLinkedRelease(string projectId, str return await httpClient.PatchAsync(updateUri, content); } + /// + /// Asynchronously creates a new component in SW360. + /// + /// The component data to create. + /// An HttpResponseMessage indicating the result of the create operation. public async Task CreateComponent(CreateComponent createComponentContent) { HttpClient httpClient = GetHttpClient(); @@ -277,6 +371,11 @@ public async Task CreateComponent(CreateComponent createCom return await httpClient.PostAsJsonAsync(sw360ComponentApi, createComponentContent); } + /// + /// Asynchronously creates a new release in SW360. + /// + /// The release data to create. + /// An HttpResponseMessage indicating the result of the create operation. public async Task CreateRelease(Releases createReleaseContent) { HttpClient httpClient = GetHttpClient(); @@ -285,6 +384,11 @@ public async Task CreateRelease(Releases createReleaseConte return await httpClient.PostAsJsonAsync(sw360ReleaseApi, createReleaseContent); } + /// + /// Asynchronously retrieves release information for a component by its identifier. + /// + /// The unique identifier of the component. + /// A JSON string containing the release data for the component. public async Task GetReleaseOfComponentById(string componentId) { HttpClient httpClient = GetHttpClient(); @@ -294,6 +398,11 @@ public async Task GetReleaseOfComponentById(string componentId) return await httpClient.GetStringAsync(componentUrl); } + /// + /// Asynchronously retrieves attachments for a release. + /// + /// The URL to retrieve release attachments from. + /// A JSON string containing the release attachments data. public async Task GetReleaseAttachments(string releaseAttachmentsUrl) { HttpClient httpClient = GetHttpClient(); @@ -301,6 +410,11 @@ public async Task GetReleaseAttachments(string releaseAttachmentsUrl) return await httpClient.GetStringAsync(releaseAttachmentsUrl); } + /// + /// Asynchronously retrieves information about a specific attachment. + /// + /// The URL of the attachment to retrieve information for. + /// A JSON string containing the attachment information. public async Task GetAttachmentInfo(string attachmentUrl) { HttpClient httpClient = GetHttpClient(); @@ -308,6 +422,11 @@ public async Task GetAttachmentInfo(string attachmentUrl) return await httpClient.GetStringAsync(attachmentUrl); } + /// + /// Downloads an attachment using WebClient to a specified file. + /// + /// The download link for the attachment. + /// The destination file name to save the attachment. public void DownloadAttachmentUsingWebClient(string attachmentDownloadLink, string fileName) { var ur = new Uri(attachmentDownloadLink); @@ -319,6 +438,12 @@ public void DownloadAttachmentUsingWebClient(string attachmentDownloadLink, stri } } + /// + /// Asynchronously updates an existing release in SW360. + /// + /// The unique identifier of the release to update. + /// The HTTP content containing the update data. + /// An HttpResponseMessage indicating the result of the update operation. public async Task UpdateRelease(string releaseId, HttpContent httpContent) { HttpClient httpClient = GetHttpClient(); @@ -328,6 +453,12 @@ public async Task UpdateRelease(string releaseId, HttpConte return await httpClient.PatchAsync(releaseApi, httpContent); } + /// + /// Asynchronously updates an existing component in SW360. + /// + /// The unique identifier of the component to update. + /// The HTTP content containing the update data. + /// An HttpResponseMessage indicating the result of the update operation. public async Task UpdateComponent(string componentId, HttpContent httpContent) { HttpClient httpClient = GetHttpClient(); @@ -336,7 +467,12 @@ public async Task UpdateComponent(string componentId, HttpC return await httpClient.PatchAsync(componentApi, httpContent); } - + /// + /// Attaches component source to SW360 for a given report and comparison data. + /// + /// The attachment report containing source details. + /// The comparison BOM data for the component. + /// A string indicating the result of the attachment operation. public string AttachComponentSourceToSW360(AttachReport attachReport, ComparisonBomData comparisonBomData) { AttachmentHelper attachmentHelper = new AttachmentHelper(sw360AuthTokenType, sw360AuthToken, sw360ReleaseApi); @@ -344,6 +480,11 @@ public string AttachComponentSourceToSW360(AttachReport attachReport, Comparison return attachmentHelper.AttachComponentSourceToSW360(attachReport, comparisonBomData); } + /// + /// Asynchronously retrieves releases by component name. + /// + /// The name of the component to search releases for. + /// A JSON string containing the release data. public async Task GetReleaseByCompoenentName(string componentName) { HttpClient httpClient = GetHttpClient(); @@ -353,6 +494,11 @@ public async Task GetReleaseByCompoenentName(string componentName) return await httpClient.GetStringAsync(url); } + /// + /// Asynchronously retrieves component details by its URL. + /// + /// The URL link to the component. + /// An HttpResponseMessage containing the component details. public async Task GetComponentDetailsByUrl(string componentLink) { HttpClient httpClient = GetHttpClient(); @@ -360,6 +506,11 @@ public async Task GetComponentDetailsByUrl(string component return await httpClient.GetAsync(componentLink); } + /// + /// Asynchronously retrieves a component by its name. + /// + /// The name of the component to retrieve. + /// A JSON string containing the component data. public async Task GetComponentByName(string componentName) { HttpClient httpClient = GetHttpClient(); @@ -368,6 +519,12 @@ public async Task GetComponentByName(string componentName) await LogHandlingHelper.HttpRequestHandling("Get Component By Name", $"MethodName:GetComponentByName()", httpClient, url); return await httpClient.GetStringAsync(url); } + + /// + /// Asynchronously retrieves a component using its name and returns the full HTTP response. + /// + /// The name of the component to retrieve. + /// An HttpResponseMessage containing the component data. public async Task GetComponentUsingName(string componentName) { HttpClient httpClient = GetHttpClient(); @@ -375,6 +532,13 @@ public async Task GetComponentUsingName(string componentNam string url = $"{sw360ComponentApi}{ApiConstant.ComponentNameUrl}{componentName}"; return await httpClient.GetAsync(url); } + + /// + /// Asynchronously retrieves all releases with complete data using pagination. + /// + /// The page number to retrieve. + /// The number of entries per page. + /// An HttpResponseMessage containing the paginated release data with all details. public async Task GetAllReleasesWithAllData(int page, int pageEntries) { HttpClient httpClient = GetHttpClient(); @@ -383,10 +547,11 @@ public async Task GetAllReleasesWithAllData(int page, int p await LogHandlingHelper.HttpRequestHandling("Get All Releases With All Data", $"MethodName:GetAllReleasesWithAllData()", httpClient, url); return await httpClient.GetAsync(url); } - #endregion - - #region PRIVATE METHODS + /// + /// Creates and configures an HttpClient instance with authentication and timeout settings. + /// + /// A configured HttpClient instance for SW360 API communication. private HttpClient GetHttpClient() { var handler = new RetryHttpClientHandler() @@ -403,6 +568,6 @@ private HttpClient GetHttpClient() return httpClient; } - #endregion + #endregion Methods } } diff --git a/src/LCT.Common/CommonHelper.cs b/src/LCT.Common/CommonHelper.cs index f11c46120..69171e5a0 100644 --- a/src/LCT.Common/CommonHelper.cs +++ b/src/LCT.Common/CommonHelper.cs @@ -1,4 +1,4 @@ -// -------------------------------------------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------------------------------------------- // SPDX-FileCopyrightText: 2025 Siemens AG // // SPDX-License-Identifier: MIT @@ -28,12 +28,40 @@ namespace LCT.Common /// public static class CommonHelper { + #region Fields + + /// + /// The logger instance for logging messages and errors. + /// static readonly ILog Logger = LoggerFactory.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// Array of invalid characters for project names. + /// private static readonly char[] InvalidProjectNameChars = new char[] { '/', '\\', '.' }; + + #endregion Fields + + #region Properties + + /// + /// Gets or sets the project summary link. + /// public static string ProjectSummaryLink { get; set; } + + /// + /// Gets or sets the default log path. + /// public static string DefaultLogPath { get; set; } - #region public + #endregion Properties + + #region Methods + + /// + /// Determines whether Azure DevOps debug mode is enabled. + /// + /// True if debug mode is enabled; otherwise, false. public static bool IsAzureDevOpsDebugEnabled() { string azureDevOpsDebug = System.Environment.GetEnvironmentVariable("System.Debug"); @@ -44,6 +72,13 @@ public static bool IsAzureDevOpsDebugEnabled() return false; } + /// + /// Removes excluded components from the component list. + /// + /// The list of components to process. + /// The list of components to exclude. + /// The count of excluded components. + /// The filtered list of components. public static List RemoveExcludedComponents(List ComponentList, List ExcludedComponents, ref int noOfExcludedComponents) { List ExcludedComponentsFromPurl = ExcludedComponents?.Where(ec => ec.StartsWith("pkg:")).ToList(); @@ -54,6 +89,12 @@ public static List RemoveExcludedComponents(List Component return ComponentList; } + /// + /// Removes invalid dependencies and references that don't match component BOM references. + /// + /// The list of components. + /// The list of dependencies to validate. + /// The cleaned list of dependencies. public static List RemoveInvalidDependenciesAndReferences(List components, List dependencies) { var componentBomRefs = new HashSet(components.Select(c => c.BomRef)); @@ -68,6 +109,12 @@ public static List RemoveInvalidDependenciesAndReferences(List + /// Gets the substring after the last occurrence of a separator. + /// + /// The input string. + /// The separator to search for. + /// The substring after the last occurrence of the separator. public static string GetSubstringOfLastOccurance(string value, string separator) { string result = string.IsNullOrWhiteSpace(value) ? string.Empty : value; @@ -78,6 +125,14 @@ public static string GetSubstringOfLastOccurance(string value, string separator) return result; } + + /// + /// Trims the specified suffix from the end of the input string if present. + /// + /// The input string. + /// The suffix to remove. + /// The string comparison type. + /// The string with the suffix removed, or the original string. public static string TrimEndOfString(this string input, string suffixToRemove, StringComparison comparisonType = StringComparison.CurrentCulture) { if (suffixToRemove != null && input.EndsWith(suffixToRemove, comparisonType)) @@ -89,11 +144,11 @@ public static string TrimEndOfString(this string input, string suffixToRemove, S } /// - /// Get display name for given instance type and property name + /// Gets the display name for the given instance type and property name. /// - /// pass the object - /// Property - /// string + /// The object instance. + /// The property name. + /// The display name attribute value, or empty string if not found. public static string Convert(object objectValue, object nameOfProperty) { var attribute = objectValue.GetType() @@ -105,6 +160,11 @@ public static string Convert(object objectValue, object nameOfProperty) return attribute != null ? attribute.DisplayName : string.Empty; } + /// + /// Checks if a string value is null, empty, or whitespace and logs an error if so. + /// + /// The name of the parameter being checked. + /// The value to check. public static void CheckNullOrEmpty(string name, string value) { if (string.IsNullOrWhiteSpace(value)) @@ -114,6 +174,12 @@ public static void CheckNullOrEmpty(string name, string value) } } + /// + /// Checks if a component has a property with the specified name. + /// + /// The component to check. + /// The property name to look for. + /// True if the property exists; otherwise, false. public static bool ComponentPropertyCheck(Component component, string constant) { if (component.Properties == null) @@ -123,6 +189,12 @@ public static bool ComponentPropertyCheck(Component component, string constant) return component.Properties.Exists(x => x.Name == constant); } + /// + /// Adds details for manually added components to the BOM list. + /// + /// The components to process. + /// The target list to add processed components to. + /// The file path to extract properties from. public static void GetDetailsForManuallyAdded(List componentsForBOM, List listComponentForBOM, string filePath) { foreach (var component in componentsForBOM) @@ -149,6 +221,11 @@ public static void GetDetailsForManuallyAdded(List componentsForBOM, } } + /// + /// Adds specific values to BOM format and serializes it to JSON. + /// + /// The BOM to format and serialize. + /// The serialized BOM JSON string. public static string AddSpecificValuesToBOMFormat(Bom listOfComponentsToBom) { string guid = Guid.NewGuid().ToString(); @@ -160,6 +237,12 @@ public static string AddSpecificValuesToBOMFormat(Bom listOfComponentsToBom) var serializedBomData = CycloneDX.Json.Serializer.Serialize(listOfComponentsToBom); return serializedBomData; } + + /// + /// Gets the list of repositories based on the project type configuration. + /// + /// The application settings containing repository configurations. + /// An array of repository names. public static string[] GetRepoList(CommonAppSettings appSettings) { var projectTypeMappings = new Dictionary> @@ -203,6 +286,14 @@ public static string[] GetRepoList(CommonAppSettings appSettings) return Array.Empty(); } + + /// + /// Initializes the log folder based on application settings. + /// + /// The application settings. + /// The log file name. + /// Whether verbose logging is enabled. + /// The log folder path. public static string LogFolderInitialization(CommonAppSettings appSettings, string logFileName, bool m_Verbose) { string FolderPath; @@ -228,7 +319,12 @@ public static string LogFolderInitialization(CommonAppSettings appSettings, stri } CopyInitialLogsToCurrentLoggerAndDelete(defaultLogFilePath); return FolderPath; - } + } + + /// + /// Copies initial logs to the current logger and deletes the original log file. + /// + /// The path to the default log file. private static void CopyInitialLogsToCurrentLoggerAndDelete(string defaultLogFilePath) { try @@ -253,6 +349,12 @@ private static void CopyInitialLogsToCurrentLoggerAndDelete(string defaultLogFil Logger.Debug("Unauthorized Access while Copying initial logs.", uaEx); } } + + /// + /// Trims the log header from a log line, returning only the message content. + /// + /// The log line to trim. + /// The message content after the header. private static string TrimLogHeader(string line) { int first = line.IndexOf('|'); @@ -267,6 +369,13 @@ private static string TrimLogHeader(string line) // Return content after the third pipe, trimming leading spaces return line[(third + 1)..].TrimStart(); } + + /// + /// Initializes the default log folder in the temp directory. + /// + /// The log file name. + /// Whether verbose logging is enabled. + /// The local path for the source repository downloads. public static string DefaultLogFolderInitialization(string logFileName, bool m_Verbose) { string localPathforSourceRepo = string.Empty; @@ -301,6 +410,13 @@ public static string DefaultLogFolderInitialization(string logFileName, bool m_V } return localPathforSourceRepo; } + + /// + /// Checks if a project name contains invalid characters. + /// + /// The project name to validate. + /// Output parameter containing the invalid characters found. + /// True if invalid characters are found; otherwise, false. public static bool ContainsInvalidCharacters(string projectName, out string invalidChars) { var foundInvalidChars = projectName.Where(c => InvalidProjectNameChars.Contains(c)) @@ -310,6 +426,15 @@ public static bool ContainsInvalidCharacters(string projectName, out string inva invalidChars = string.Join(", ", foundInvalidChars.Select(c => $"'{c}'")); return foundInvalidChars.Count != 0; } + + /// + /// Validates the SW360 project name and state. + /// + /// The SW360 project name. + /// The clearing state of the project. + /// The project name to validate. + /// The application settings. + /// 0 if valid; -1 if invalid. public static int ValidateSw360Project(string sw360ProjectName, string clearingState, string Name, CommonAppSettings appSettings) { if (string.IsNullOrEmpty(sw360ProjectName)) @@ -334,6 +459,12 @@ public static int ValidateSw360Project(string sw360ProjectName, string clearingS } return 0; } + + /// + /// Masks sensitive arguments like tokens in the argument array. + /// + /// The array of arguments to mask. + /// A new array with sensitive values masked. public static string[] MaskSensitiveArguments(string[] args) { if (args == null || args.Length == 0) @@ -371,6 +502,13 @@ public static string[] MaskSensitiveArguments(string[] args) return maskedArgs; } + /// + /// Removes excluded components from the BOM based on application settings. + /// + /// The application settings containing exclusion rules. + /// The BOM to process. + /// Optional callback to update KPI with exclusion count. + /// The BOM with excluded components removed. public static Bom RemoveExcludedComponentsFromBom(CommonAppSettings appSettings, Bom cycloneDXBOM, Action updateKpiCallback = null) { List componentForBOM = cycloneDXBOM.Components.ToList(); @@ -468,6 +606,12 @@ public static void SetComponentPropertiesAndHashes(Component component, }; } } + + /// + /// Adds SPDX SBOM filename properties to all components in the BOM. + /// + /// The BOM to update. + /// The SPDX file path. public static void AddSpdxSBomFileNameProperty(ref Bom bom, string filePath) { if (bom?.Components != null) @@ -483,30 +627,60 @@ public static void AddSpdxSBomFileNameProperty(ref Bom bom, string filePath) } } + + /// + /// Removes duplicate properties by name and adds a new property. + /// + /// The list of properties to update. + /// The property name. + /// The property value. public static void RemoveDuplicateAndAddProperty(ref List properties, string propertyName, string propertyValue) { properties ??= new List(); properties.RemoveAll(p => p.Name == propertyName); properties.Add(new Property { Name = propertyName, Value = propertyValue }); } + + /// + /// Constructs the SW360 release URL. + /// + /// The SW360 environment URL. + /// The release ID. + /// The complete SW360 release URL. public static string Sw360URL(string sw360Env, string releaseId) { string sw360URL = $"{sw360Env}{"/group/guest/components/-/component/release/detailRelease/"}{releaseId}"; return sw360URL; } + + /// + /// Constructs the SW360 component URL. + /// + /// The SW360 environment URL. + /// The component ID. + /// The complete SW360 component URL. public static string Sw360ComponentURL(string sw360Env, string componentId) { string sw360URL = $"{sw360Env}{"/group/guest/components/-/component/detail/"}{componentId}"; return sw360URL; } - #endregion - #region private + /// + /// Converts a wildcard pattern to a regular expression pattern. + /// + /// The wildcard pattern. + /// The equivalent regex pattern. private static string WildcardToRegex(string wildcard) { return "^" + Regex.Escape(wildcard).Replace("\\*", ".*") + "$"; } + /// + /// Adds excluded component property based on PURL matching. + /// + /// The list of components. + /// The list of PURLs to exclude. + /// The count of excluded components. private static void AddExcludedComponentsPropertyFromPurl(List ComponentList, List ExcludedComponentsFromPurl, ref int noOfExcludedComponents) { foreach (string excludedComponent in ExcludedComponentsFromPurl) @@ -526,6 +700,12 @@ private static void AddExcludedComponentsPropertyFromPurl(List Compon } } } + + /// + /// Normalizes a PURL by replacing encoded characters. + /// + /// The PURL to normalize. + /// The normalized PURL. private static string NormalizePurl(string purl) { if (purl.Contains("%40")) @@ -534,6 +714,13 @@ private static string NormalizePurl(string purl) } return purl; } + + /// + /// Adds excluded component property based on name and version matching. + /// + /// The list of components. + /// The list of excluded components by name:version. + /// The count of excluded components. private static void AddExcludedComponentsPropertyFromNameAndVersion(List ComponentList, List otherExcludedComponents, ref int noOfExcludedComponents) { foreach (string excludedComponent in otherExcludedComponents) @@ -559,6 +746,14 @@ private static void AddExcludedComponentsPropertyFromNameAndVersion(List + /// Creates a component with standard properties. + /// + /// The component name. + /// The component version. + /// The release external ID (PURL). + /// A new Component instance. public static Component CreateComponentWithProperties(string name, string version, string releaseExternalId) { Component component = new Component @@ -571,6 +766,12 @@ public static Component CreateComponentWithProperties(string name, string versio }; return component; } + + /// + /// Canonicalizes the project type string to standardized format. + /// + /// The project type to canonicalize. + /// The canonicalized project type string. public static string CanonicalizeProjectType(string projectType) { if (string.IsNullOrWhiteSpace(projectType)) @@ -589,6 +790,7 @@ public static string CanonicalizeProjectType(string projectType) _ => projectType.Trim(), }; } - #endregion + + #endregion Methods } } \ No newline at end of file diff --git a/src/LCT.Common/ComplianceValidator/ComplianceCheck.cs b/src/LCT.Common/ComplianceValidator/ComplianceCheck.cs index 521fa0397..0ef7fac73 100644 --- a/src/LCT.Common/ComplianceValidator/ComplianceCheck.cs +++ b/src/LCT.Common/ComplianceValidator/ComplianceCheck.cs @@ -19,18 +19,31 @@ namespace LCT.Common.ComplianceValidator { public class ComplianceCheck : IChecker { + #region Fields + /// + /// Logger instance for compliance check logging. + /// private static readonly ILog Logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + /// + /// Stores warning messages generated during compliance checks. + /// private List Warnings = new(); + #endregion + #region Properties + // No properties present. + #endregion + + #region Constructors + // No constructors present. + #endregion + + #region Methods /// /// Asynchronously loads compliance settings from a JSON file. /// - /// This method reads the specified JSON file and deserializes its content into a object. Ensure the file exists and contains valid JSON data that matches - /// the structure of . /// The full path to the JSON file containing the compliance settings. Must not be null or empty. - /// A task that represents the asynchronous operation. The task result contains a object populated with the settings from the specified JSON file. + /// A task that represents the asynchronous operation. The task result contains a ComplianceSettingsModel object populated with the settings from the specified JSON file. public async Task LoadSettingsAsync(string jsonFilePath) { using var stream = System.IO.File.OpenRead(jsonFilePath); @@ -41,16 +54,9 @@ public async Task LoadSettingsAsync(string jsonFilePath /// /// Evaluates compliance settings and data to determine if any compliance warnings or recommendations exist. /// - /// This method processes the provided compliance settings and data to identify any - /// compliance exceptions. If compliance warnings are found, they are logged and displayed, along with any - /// associated recommendations. The method returns if warnings are present or if the - /// input data is invalid. - /// The compliance settings model containing exception components and compliance instructions. Cannot be . - /// The data to be checked for compliance. Must be a of - /// objects. If the data is not of the expected type or is , the method returns . - /// if no compliance warnings are detected; otherwise, . + /// The compliance settings model containing exception components and compliance instructions. Cannot be null. + /// The data to be checked for compliance. Must be a List of ComparisonBomData objects. If the data is not of the expected type or is null, the method returns false. + /// True if no compliance warnings are detected; otherwise, false. public bool Check(ComplianceSettingsModel settings, object data) { Warnings = []; @@ -78,6 +84,11 @@ public bool Check(ComplianceSettingsModel settings, object data) return hasWarning; } + /// + /// Builds a dictionary mapping PURL strings to their corresponding compliance exception components. + /// + /// The collection of compliance exception components. + /// A dictionary mapping PURL strings to compliance exception components. private static Dictionary BuildPurlToComponentMap(IEnumerable components) { var map = new Dictionary(); @@ -92,6 +103,12 @@ private static Dictionary BuildPurlToCompo return map; } + /// + /// Groups BOM data by warning and recommendation messages. + /// + /// The list of BOM data to group. + /// The dictionary mapping PURLs to compliance exception components. + /// A dictionary with keys as (warning, recommendation) and values as lists of affected PURLs. private static Dictionary<(string warning, string recommendation), List> GroupBomDataByWarningAndRecommendation( List bomDataList, Dictionary purlToComponent) @@ -116,6 +133,13 @@ private static Dictionary BuildPurlToCompo return groupMap; } + /// + /// Handles a group of warnings and recommendations, logging them and returning whether a warning was present. + /// + /// The warning message. + /// The recommendation message. + /// The list of affected PURLs. + /// True if a warning was present; otherwise, false. private bool HandleGroup(string warning, string recommendation, List purls) { bool hasWarning = false; @@ -142,9 +166,8 @@ private bool HandleGroup(string warning, string recommendation, List pur /// /// Logs the provided recommendation content as an informational message. /// - /// If the is null, empty, or contains only whitespace, the - /// method does nothing. /// The recommendation content to log. Must not be null, empty, or consist only of whitespace. + /// void. public void PrintRecommendation(string content) { if (string.IsNullOrWhiteSpace(content)) @@ -156,9 +179,8 @@ public void PrintRecommendation(string content) /// /// Logs a warning message with the specified content. /// - /// If the is null, empty, or contains only whitespace, the - /// method does nothing. /// The warning message to log. Must not be null, empty, or consist only of whitespace. + /// void. public void PrintWarning(string content) { if (string.IsNullOrWhiteSpace(content)) @@ -175,5 +197,10 @@ public List GetResults() { return Warnings; } + #endregion + + #region Events + // No events present. + #endregion } } \ No newline at end of file diff --git a/src/LCT.Common/ComponentEqualityComparer.cs b/src/LCT.Common/ComponentEqualityComparer.cs index 3b8829bb3..fe29cdc7b 100644 --- a/src/LCT.Common/ComponentEqualityComparer.cs +++ b/src/LCT.Common/ComponentEqualityComparer.cs @@ -11,10 +11,18 @@ namespace LCT.Common { /// - /// Comparer class + /// Provides equality comparison for Component objects based on Name, Version, and Purl. /// public class ComponentEqualityComparer : IEqualityComparer { + #region Methods + + /// + /// Determines whether two Component objects are equal. + /// + /// The first component to compare. + /// The second component to compare. + /// True if the components are equal; otherwise, false. public bool Equals(Component x, Component y) { if (x == null && y == null) @@ -27,9 +35,16 @@ public bool Equals(Component x, Component y) return false; } + /// + /// Gets the hash code for the specified Component object. + /// + /// The component to get the hash code for. + /// A hash code based on the component's Name, Version, and Purl. public int GetHashCode(Component obj) { return HashCode.Combine(obj.Name, obj.Version, obj.Purl); } + + #endregion } } diff --git a/src/LCT.Common/Constants/Dataconstant.cs b/src/LCT.Common/Constants/Dataconstant.cs index afe9da66a..1ce741039 100644 --- a/src/LCT.Common/Constants/Dataconstant.cs +++ b/src/LCT.Common/Constants/Dataconstant.cs @@ -15,6 +15,10 @@ namespace LCT.Common.Constants [ExcludeFromCodeCoverage] public static class Dataconstant { + #region Fields + /// + /// Dictionary of package type to purl id. + /// private static Dictionary purlids = new Dictionary { {"NPM", "pkg:npm"}, @@ -26,67 +30,249 @@ public static class Dataconstant {"ALPINE", "pkg:apk/alpine"}, {"CARGO", "pkg:cargo"}, }; - - //Identified types + /// + /// Identified type: Manually added. + /// public const string ManullayAdded = "ManuallyAdded"; + /// + /// Identified type: Discovered. + /// public const string Discovered = "Discovered"; + /// + /// Identified type: Template added. + /// public const string TemplateAdded = "TemplateAdded"; + /// + /// Identified type: Template updated. + /// public const string TemplateUpdated = "TemplateUpdated"; - + /// + /// State: Created. + /// public const string Created = "Created"; + /// + /// State: Newly created. + /// public const string NewlyCreated = "Newly Created"; + /// + /// State: Uploaded. + /// public const string Uploaded = "Uploaded"; + /// + /// State: Available. + /// public const string Available = "Available"; + /// + /// State: Not created. + /// public const string NotCreated = "Not Created"; + /// + /// State: Not uploaded. + /// public const string NotUploaded = "Not Uploaded"; + /// + /// State: New clearing. + /// public const string NewClearing = "NEW_CLEARING"; + /// + /// State: Approved. + /// public const string Approved = "APPROVED"; + /// + /// State: Not available. + /// public const string NotAvailable = "Not Available"; + /// + /// State: Not configured. + /// public const string NotConfigured = "Not Configured"; + /// + /// State: Already uploaded. + /// public const string AlreadyUploaded = "Already Uploaded"; + /// + /// Error: Node module path not found. + /// public const string NodeModulePathNotFound = "Node Module Path not Found"; + /// + /// Error: Component download URL not found. + /// public const string DownloadUrlNotFound = "Component Download Url not Found!"; + /// + /// Error: Source URL not found. + /// public const string SourceUrlNotFound = "Source URL not found"; + /// + /// Error: Package URL not found. + /// public const string PackageUrlNotFound = "Package URL not found"; + /// + /// Error: Package name not found in JFrog. + /// public const string PackageNameNotFoundInJfrog = "Package name not found in Jfrog"; + /// + /// Error: JFrog repo path not found. + /// public const string JfrogRepoPathNotFound = "Jfrog repo path not found"; + /// + /// Error: Not found in JFrog repo. + /// public const string NotFoundInJFrog = "Not Found in JFrogRepo"; + /// + /// Linked by CA Tool. + /// public const string LinkedByCATool = "Linked by CA Tool"; + /// + /// Linked by CA Tool release relation: UNKNOWN. + /// public const string LinkedByCAToolReleaseRelation = "UNKNOWN"; + /// + /// Linked by CA Tool release relation: CONTAINED. + /// public const string LinkedByCAToolReleaseRelationContained = "CONTAINED"; + /// + /// Release attachment comment. + /// public const string ReleaseAttachmentComment = "Attached by CA Tool"; + /// + /// Forward slash character. + /// public const char ForwardSlash = '/'; + /// + /// Suffix for source URL. + /// public const string SourceURLSuffix = "/srcfiles?fileinfo=1"; + /// + /// CycloneDX Artifactory repo name key. + /// public const string Cdx_ArtifactoryRepoName = "internal:siemens:clearing:jfrog-repo-name"; + /// + /// CycloneDX project type key. + /// public const string Cdx_ProjectType = "internal:siemens:clearing:project-type"; + /// + /// CycloneDX clearing state key. + /// public const string Cdx_ClearingState = "internal:siemens:clearing:clearing-state"; + /// + /// CycloneDX is internal key. + /// public const string Cdx_IsInternal = "internal:siemens:clearing:is-internal"; + /// + /// CycloneDX release URL key. + /// public const string Cdx_ReleaseUrl = "internal:siemens:clearing:sw360:release-url"; + /// + /// CycloneDX Fossology URL key. + /// public const string Cdx_FossologyUrl = "internal:siemens:clearing:fossology:url"; + /// + /// CycloneDX is development key. + /// public const string Cdx_IsDevelopment = "internal:siemens:clearing:development"; + /// + /// CycloneDX identifier type key. + /// public const string Cdx_IdentifierType = "internal:siemens:clearing:identifier-type"; + /// + /// Suffix for Alpine source URL. + /// public const string AlpineSourceURLSuffix = "?ref_type=heads"; + /// + /// CycloneDX JFrog repo path key. + /// public const string Cdx_JfrogRepoPath = "internal:siemens:clearing:jfrog-repo-path"; + /// + /// CycloneDX Siemens filename key. + /// public const string Cdx_Siemensfilename = "internal:siemens:clearing:siemens:filename"; + /// + /// CycloneDX Siemens direct key. + /// public const string Cdx_SiemensDirect = "internal:siemens:clearing:siemens:direct"; + /// + /// CycloneDX exclude component key. + /// public const string Cdx_ExcludeComponent = "internal:siemens:clearing:sw360:exclude"; + /// + /// Production Fossology URL. + /// public const string ProductionFossologyURL = "automation.fossology"; + /// + /// Stage Fossology URL. + /// public const string StageFossologyURL = "stage.fossology"; + /// + /// Scan available state. + /// public const string ScanAvailableState = "SCAN_AVAILABLE"; + /// + /// Sent to clearing state. + /// public const string SentToClearingState = "SENT_TO_CLEARING_TOOL"; + /// + /// Type jar suffix. + /// public const string TypeJarSuffix = "?type=jar"; + /// + /// GitHub URL for continuous-clearing. + /// public const string GithubUrl = "https://github.com/siemens/continuous-clearing"; + /// + /// Standard SBOM URL. + /// public const string StandardSbomUrl = "https://sbom.siemens.io/"; + /// + /// SBOM spec version string. + /// public const string SbomSpecVersionString = "1.6"; + /// + /// Moderation request message. + /// public const string ModerationRequestMessage = "Moderation request is created"; + /// + /// CycloneDX SPDX file name key. + /// public const string Cdx_SpdxFileName = "internal:siemens:clearing:spdx-file-name"; + /// + /// SPDX import string. + /// public const string SpdxImport = "SPDXImport"; + /// + /// Identifier string. + /// public const string Identifier = "Identifier"; + /// + /// Creator string. + /// public const string Creator = "Creator"; + /// + /// Uploader string. + /// public const string Uploader = "Uploader"; + #endregion + + #region Properties + // No properties present. + #endregion + + #region Constructors + // No constructors present. + #endregion + + #region Methods + /// + /// Gets the dictionary of package type to purl id. + /// + /// The dictionary mapping package type to purl id. public static Dictionary PurlCheck() { return purlids; } + #endregion + + #region Events + // No events present. + #endregion } } diff --git a/src/LCT.Common/Constants/FileConstant.cs b/src/LCT.Common/Constants/FileConstant.cs index c5da3d244..245d1125f 100644 --- a/src/LCT.Common/Constants/FileConstant.cs +++ b/src/LCT.Common/Constants/FileConstant.cs @@ -15,52 +15,208 @@ namespace LCT.Common.Constants [ExcludeFromCodeCoverage] public static class FileConstant { + #region Fields + /// + /// File name for components without download URL. + /// public const string ComponentsWithoutSrcFileName = "ComponentsWithoutDownloadURL.json"; + /// + /// File name for components without source attachment in SW360. + /// public const string SourceAttachmentNotAvailableInSw360 = "ComponentsWithoutSourceAttachmentInSW360.json"; + /// + /// Default BOM file name. + /// public const string BomFileName = "Bom.cdx.json"; + /// + /// KPI data file name for BOM. + /// public const string BomKpiDataFileName = "PackageIdentifierKpiData.json"; + /// + /// KPI data file name for creator. + /// public const string CreatorKpiDataFileName = "PacakageCreatorKpiData.json"; + /// + /// KPI data file name for uploader. + /// public const string UploaderKpiDataFileName = "FossUploaderKpiData.json"; + /// + /// File extension for zip files. + /// public const string ZipFileExtension = ".zip"; + /// + /// File extension for tgz files. + /// public const string TgzFileExtension = ".tgz"; + /// + /// File extension for tar.gz files. + /// public const string TargzFileExtension = ".tar.gz"; + /// + /// File extension for NuGet package files. + /// public const string NuspecFileExtension = ".nupkg"; + /// + /// Log file name prefix for BOM. + /// public const string BomLogFileNamePrefix = "PackageIdentifier_"; + /// + /// Log file name prefix for creator. + /// public const string CreatorLogFileNamePrefix = "PackageCreator_"; + /// + /// Log file name prefix for uploader. + /// public const string UploaderFileNamePrefix = "Fossology_"; + /// + /// File name for package-lock.json. + /// public const string PackageLockFileName = "package-lock.json"; + /// + /// File name for packages.config. + /// public const string PackageConfigFileName = "packages.config"; + /// + /// File name for packages.lock.json. + /// public const string PackageLockJonFileName = "packages.lock.json"; + /// + /// Folder name for logs. + /// public const string LogFolder = "Logs"; - public const string ComponentCreatorLog = "PackageCreator"; - public const string BomCreatorLog = "PackageIdentifier"; + /// + /// Log file name for component creator. + /// + public const string ComponentCreatorLog = "PackageCreator.log"; + /// + /// Log file name for BOM creator. + /// + public const string BomCreatorLog = "PackageIdentifier.log"; + /// + /// Log file name for Fossology uploader. + /// public const string FossologyUploaderLog = "FossologyUploader.log"; - public const string ArtifactoryUploaderLog = "ArtifactoryUploader"; + /// + /// Log file name for Artifactory uploader. + /// + public const string ArtifactoryUploaderLog = "ArtifactoryUploader.log"; + /// + /// File extension for tar.xz files. + /// public const string XzFileExtension = ".tar.xz"; + /// + /// File extension for tar.bz2 files. + /// public const string Bz2FileExtension = ".tar.bz2"; + /// + /// File extension for orig.tar files. + /// public const string OrigTarFileExtension = ".orig.tar."; + /// + /// File extension for debian.tar files. + /// public const string DebianTarFileExtension = ".debian.tar."; + /// + /// File extension for debian diff files. + /// public const string DebianFileExtension = ".diff."; + /// + /// File extension for debian combined patch files. + /// public const string DebianCombinedPatchExtension = "-debian-combined.tar.bz2"; + /// + /// File extension for DSC files. + /// public const string DSCFileExtension = ".dsc"; + /// + /// Directory path for container files. + /// public static readonly string ContainerDir = Path.Combine(@"/app/opt/PatchedFiles"); + /// + /// Docker image name. + /// public const string DockerImage = "ghcr.io/siemens/continuous-clearing"; + /// + /// Docker command tool path. + /// public static readonly string DockerCMDTool = Path.Combine(@"/bin/bash"); + /// + /// File name for package.json. + /// public const string PackageJsonFileName = "package.json"; + /// + /// File name for appSettings.json. + /// public const string appSettingFileName = "appSettings.json"; + /// + /// File extension for CycloneDX files. + /// public const string CycloneDXFileExtension = ".cdx.json"; + /// + /// File extension for SBOM template files. + /// public const string SBOMTemplateFileExtension = "CATemplate.cdx.json"; + /// + /// File name for NuGet asset files. + /// public const string NugetAssetFile = "project.assets.json"; + /// + /// File name for multiple versions file. + /// public const string multipleversionsFileName = "Multipleversions.json"; + /// + /// File name for Artifactory report not approved. + /// public const string artifactoryReportNotApproved = "ReportNotApproved.json"; + /// + /// Basic SBOM name. + /// public const string basicSBOMName = "ContinuousClearing"; + /// + /// File extensions for NuGet deployment type detection. + /// public static readonly string[] Nuget_DeploymentType_DetectionExt = ["*.csproj", "*.Build.props"]; + /// + /// Tags for NuGet deployment type detection. + /// public static readonly string[] Nuget_DeploymentType_DetectionTags = ["SelfContained"]; + /// + /// Backup key name. + /// public const string backUpKey = "Backup"; + /// + /// File extension for SPDX files. + /// public const string SPDXFileExtension = ".spdx.sbom.json"; + /// + /// File extension for Conan files. + /// public const string ConanFileExtension = ".dep.json"; + /// + /// File extension for Cargo files. + /// public const string CargoFileExtension = "metadata.json"; + /// + /// File extension for crate files. + /// public const string CrateFileExtension = ".crate"; + #endregion + + #region Properties + // No properties present. + #endregion + + #region Constructors + // No constructors present. + #endregion + + #region Methods + // No methods present. + #endregion + + #region Events + // No events present. + #endregion } } diff --git a/src/LCT.Common/Constants/TelemetryConstant.cs b/src/LCT.Common/Constants/TelemetryConstant.cs index cbf32915f..b96fef365 100644 --- a/src/LCT.Common/Constants/TelemetryConstant.cs +++ b/src/LCT.Common/Constants/TelemetryConstant.cs @@ -10,14 +10,59 @@ namespace LCT.Common.Constants [ExcludeFromCodeCoverage] public static class TelemetryConstant { + #region Fields + /// + /// The name of the tool. + /// public const string ToolName = "CATool"; + /// + /// Telemetry key for package identifier execution. + /// public const string PackageIdentifier = "PackageIdentifierExecution"; + /// + /// Telemetry key for package creator execution. + /// public const string PackageCreator = "PackageCreatorExecution"; + /// + /// Telemetry key for Artifactory uploader execution. + /// public const string ArtifactoryUploader = "ArtifactoryUploaderExecution"; + /// + /// Telemetry key for identifier KPI data. + /// public const string IdentifierKpiData = "IdentifierKpiDataTelemetry"; + /// + /// Telemetry key for creator KPI data. + /// public const string CreatorKpiData = "CreatorKpiDataTelemetry"; + /// + /// Telemetry key for Artifactory uploader KPI data. + /// public const string ArtifactoryUploaderKpiData = "UploaderKpiDataTelemetry"; + /// + /// The type of telemetry (e.g., ApplicationInsights). + /// public const string Type = "ApplicationInsights"; + /// + /// The log message displayed when telemetry tracking starts. + /// public const string StartLogMessage = "Telemetry tracking is now active for this execution. To turn off telemetry, use the command-line option --Telemetry:Enable false or adjust the settings in your appsettings file."; + #endregion + + #region Properties + // No properties present. + #endregion + + #region Constructors + // No constructors present. + #endregion + + #region Methods + // No methods present. + #endregion + + #region Events + // No events present. + #endregion } } diff --git a/src/LCT.Common/CycloneDXBomParser.cs b/src/LCT.Common/CycloneDXBomParser.cs index a8c770615..85d50e8d0 100644 --- a/src/LCT.Common/CycloneDXBomParser.cs +++ b/src/LCT.Common/CycloneDXBomParser.cs @@ -17,9 +17,24 @@ namespace LCT.Common { + /// + /// Provides parsing functionality for CycloneDX BOM files. + /// public class CycloneDXBomParser : ICycloneDXBomParser { + #region Fields + static readonly ILog Logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + #endregion + + #region Methods + + /// + /// Parses a CycloneDX BOM file and returns the BOM object. + /// + /// The file path of the CycloneDX BOM file. + /// A BOM object containing the parsed data. public Bom ParseCycloneDXBom(string filePath) { Logger.Debug("ParseCycloneDXBom():Parsing CycloneDX Bom File started"); @@ -61,6 +76,11 @@ public Bom ParseCycloneDXBom(string filePath) return bom; } + /// + /// Extracts SBOM details from a template BOM, filtering valid components. + /// + /// The template BOM to extract details from. + /// A BOM object containing extracted components, metadata, and dependencies. public static Bom ExtractSBOMDetailsFromTemplate(Bom template) { Bom bom = new Bom(); @@ -86,6 +106,11 @@ public static Bom ExtractSBOMDetailsFromTemplate(Bom template) return bom; } + /// + /// Checks and removes invalid components from the BOM based on project type. + /// + /// The list of components to validate. + /// The project type to validate against. public static void CheckValidComponentsForProjectType(List bom, string projectType) { foreach (var component in bom.ToList()) @@ -105,5 +130,6 @@ public static void CheckValidComponentsForProjectType(List bom, strin } } + #endregion } } diff --git a/src/LCT.Common/EnvironmentHelper.cs b/src/LCT.Common/EnvironmentHelper.cs index 79cd6393d..c7dbbbf4d 100644 --- a/src/LCT.Common/EnvironmentHelper.cs +++ b/src/LCT.Common/EnvironmentHelper.cs @@ -9,8 +9,17 @@ namespace LCT.Common { + /// + /// Provides helper methods for managing environment exit operations. + /// public class EnvironmentHelper : IEnvironmentHelper { + #region Methods + + /// + /// Calls environment exit with appropriate handling based on exit code. + /// + /// The exit code to use (-1, 0, or 2). public void CallEnvironmentExit(int exitCode) { if (exitCode == -1 || exitCode == 0) @@ -23,10 +32,16 @@ public void CallEnvironmentExit(int exitCode) Environment.ExitCode = 2; } } + + /// + /// Exits the environment with the specified exit code. + /// + /// The exit code to use. private static void EnvironmentExit(int exitCode) { Environment.Exit(exitCode); } + #endregion } } diff --git a/src/LCT.Common/ExceptionHandling.cs b/src/LCT.Common/ExceptionHandling.cs index ad0948a8c..6c8e384a6 100644 --- a/src/LCT.Common/ExceptionHandling.cs +++ b/src/LCT.Common/ExceptionHandling.cs @@ -14,11 +14,34 @@ namespace LCT.Common { + /// + /// Provides exception handling utilities for logging different types of exceptions. + /// public class ExceptionHandling { - protected ExceptionHandling() { } + #region Fields + private static readonly ILog Logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + #endregion + + #region Constructors + + /// + /// Prevents external instantiation of the ExceptionHandling class. + /// + protected ExceptionHandling() { } + + #endregion + + #region Methods + + /// + /// Handles HTTP exceptions and logs appropriate error messages based on status code. + /// + /// The HTTP request exception. + /// The HTTP response message. + /// The source of the exception. public static void HttpException(HttpRequestException ex, HttpResponseMessage response, string exceptionSource) { if (400 <= Convert.ToInt32(response.StatusCode) && Convert.ToInt32(response.StatusCode) <= 499) @@ -32,21 +55,37 @@ public static void HttpException(HttpRequestException ex, HttpResponseMessage re } } + + /// + /// Handles Fossology-specific exceptions and logs an error message. + /// + /// The HTTP request exception from Fossology. public static void FossologyException(HttpRequestException ex) { string message = $" The Fossology process could not be completed. Exception: {ex.Message}"; LoggerHelper.WriteFossologyExceptionMessage(message); } + /// + /// Handles argument exceptions and logs missing argument error messages. + /// + /// The message describing the missing arguments. public static void ArgumentException(string message) { Logger.Logger.Log(null, Level.Error, $"Missing Arguments: Please provide the below arguments via inline or in the appSettings.json file to proceed.", null); Logger.Logger.Log(null, Level.Warn, $"{message}", null); } + /// + /// Handles task cancellation exceptions and logs a timeout error message. + /// + /// The task canceled exception. + /// The source of the exception. public static void TaskCancelledException(TaskCanceledException ex, string exceptionSource) { Logger.Logger.Log(null, Level.Error, $"A timeout error is thrown from {exceptionSource} server,Please wait for sometime and re run the pipeline again:{ex.Message}", null); } + + #endregion } } \ No newline at end of file diff --git a/src/LCT.Common/FileOperations.cs b/src/LCT.Common/FileOperations.cs index 627268c7d..1b32246b1 100644 --- a/src/LCT.Common/FileOperations.cs +++ b/src/LCT.Common/FileOperations.cs @@ -23,11 +23,26 @@ namespace LCT.Common /// public class FileOperations : IFileOperations { + #region Fields + static readonly ILog Logger = LoggerFactory.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + #endregion + + #region Properties + public static string CatoolBomFilePath { get; set; } private const string FileOperationsMessage = "File Operations"; private const string LogMessage = "Generated FilePath: {0}"; + #endregion + + #region Methods + + /// + /// Validates that the file path exists and is not null or whitespace. + /// + /// The file path to validate. public void ValidateFilePath(string filePath) { if (string.IsNullOrWhiteSpace(filePath)) @@ -46,11 +61,12 @@ public void ValidateFilePath(string filePath) /// /// writes the content to the specified file /// - /// - /// dataToWrite - /// folderPath - /// fileNameWithExtension - /// projectName + /// The type of data to write. + /// The data to write to the file. + /// The folder path where the file will be written. + /// The file name with extension. + /// The project name to prefix the file name. + /// "success" if the operation succeeded; otherwise, "failure". public string WriteContentToFile(T dataToWrite, string folderPath, string fileNameWithExtension, string projectName) { try @@ -87,6 +103,16 @@ public string WriteContentToFile(T dataToWrite, string folderPath, string fil return "success"; } + + /// + /// Writes the content to the output BOM file. + /// + /// The type of data to write. + /// The data to write to the BOM file. + /// The folder path where the file will be written. + /// The file name with extension. + /// The project name to prefix the file name. + /// "success" if the operation succeeded; otherwise, "failure". public string WriteContentToOutputBomFile(T dataToWrite, string folderPath, string fileNameWithExtension, string projectName) { try @@ -122,6 +148,12 @@ public string WriteContentToOutputBomFile(T dataToWrite, string folderPath, s } + /// + /// Combines components from an existing BOM file with new components. + /// + /// The new BOM components to combine. + /// The file path of the existing BOM file. + /// A BOM containing the combined components and dependencies. public Bom CombineComponentsFromExistingBOM(Bom components, string filePath) { Bom comparisonData = new Bom(); @@ -184,6 +216,15 @@ public Bom CombineComponentsFromExistingBOM(Bom components, string filePath) } return comparisonData; } + + /// + /// Writes the content to a CycloneDX file. + /// + /// The type of data to write. + /// The data to write to the file. + /// The folder path where the file will be written. + /// The file name with extension to copy and write. + /// "success" if the operation succeeded; otherwise, "failure". public string WriteContentToCycloneDXFile(T dataToWrite, string filePath, string fileNameWithExtension) { try @@ -217,6 +258,11 @@ public string WriteContentToCycloneDXFile(T dataToWrite, string filePath, str } + /// + /// Backs up the given file by moving it with a timestamp prefix. + /// + /// The folder path containing the file to backup. + /// The file name to backup. private static void BackupTheGivenFile(string folderPath, string fileName) { string oldFile = Path.Combine(folderPath, fileName); @@ -250,6 +296,15 @@ private static void BackupTheGivenFile(string folderPath, string fileName) } } + /// + /// Writes the content to a report file for not approved items. + /// + /// The type of data to write. + /// The data to write to the file. + /// The folder path where the file will be written. + /// The file name with extension. + /// The name to prefix the file name. + /// "success" if the operation succeeded; otherwise, "failure". public string WriteContentToReportNotApprovedFile(T dataToWrite, string folderPath, string fileNameWithExtension, string name) { try @@ -282,6 +337,16 @@ public string WriteContentToReportNotApprovedFile(T dataToWrite, string folde return "success"; } + + /// + /// Writes the content to a file for tracking multiple versions. + /// + /// The type of data to write. + /// The data to write to the file. + /// The folder path where the file will be written. + /// The file name with extension. + /// The project name to prefix the file name. + /// "success" if the operation succeeded; otherwise, "failure". public string WriteContentToMultipleVersionsFile(T dataToWrite, string folderPath, string fileNameWithExtension, string projectName) { try @@ -316,6 +381,11 @@ public string WriteContentToMultipleVersionsFile(T dataToWrite, string folder } + /// + /// Updates the compositions section by merging source and target BOM compositions. + /// + /// The source BOM with compositions to merge. + /// The target BOM to update with compositions. private static void UpdateCompositions(ref Bom components, ref Bom comparisonData) { // Early return if there are no compositions to process @@ -347,6 +417,12 @@ private static void UpdateCompositions(ref Bom components, ref Bom comparisonDat } } + /// + /// Finds a matching composition in the compositions list based on assembly equality. + /// + /// The list of compositions to search. + /// The source composition to match. + /// The matching composition if found; otherwise, null. private static Composition FindMatchingComposition(List compositions, Composition sourceComposition) { return compositions.FirstOrDefault(c => @@ -355,6 +431,11 @@ private static Composition FindMatchingComposition(List composition c.Assemblies.SequenceEqual(sourceComposition.Assemblies)); } + /// + /// Merges dependencies from source composition to target composition. + /// + /// The source composition with dependencies to merge. + /// The target composition to receive dependencies. private static void MergeDependencies(Composition source, Composition target) { if (source.Dependencies == null || source.Dependencies.Count == 0) @@ -369,5 +450,7 @@ private static void MergeDependencies(Composition source, Composition target) var newDependencies = source.Dependencies.Where(d => !target.Dependencies.Contains(d)); target.Dependencies.AddRange(newDependencies); } + + #endregion } } diff --git a/src/LCT.Common/FileParser.cs b/src/LCT.Common/FileParser.cs index be3a203ba..ee2267f7b 100644 --- a/src/LCT.Common/FileParser.cs +++ b/src/LCT.Common/FileParser.cs @@ -12,6 +12,13 @@ namespace LCT.Common { public class FileParser : IFileParser { + #region Methods + + /// + /// Parses a TOML file and returns the parsed table. + /// + /// The file path of the TOML file to parse. + /// A TomlTable containing the parsed data, or an empty TomlTable if parsing fails. public TomlTable ParseTomlFile(string filePath) { TomlTable table; @@ -27,5 +34,7 @@ public TomlTable ParseTomlFile(string filePath) return new TomlTable(); } } + + #endregion } } diff --git a/src/LCT.Common/FolderAction.cs b/src/LCT.Common/FolderAction.cs index 0d1e62e01..f87fdec70 100644 --- a/src/LCT.Common/FolderAction.cs +++ b/src/LCT.Common/FolderAction.cs @@ -20,14 +20,23 @@ namespace LCT.Common /// public class FolderAction : IFolderAction { + #region Fields + + /// + /// The logger instance for logging messages and errors. + /// static readonly ILog Logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + #endregion + + #region Methods + /// /// Copies source directory content to target directory content /// - /// - /// - /// bool + /// The source directory path. + /// The target directory path. + /// True if the copy operation succeeded; otherwise, false. public bool CopyToTargetDirectory(string sourceDirectory, string targetDirectory) { Logger.Debug("CopyToTargetDirectory(): Start copying directory."); @@ -60,9 +69,10 @@ public bool CopyToTargetDirectory(string sourceDirectory, string targetDirectory } /// - /// Validates the folder path given + /// Validates the folder path to ensure it is not null and exists. /// - /// + /// The folder path to validate. + /// The environment helper for exiting the application on validation failure. public void ValidateFolderPath(string folderPath, IEnvironmentHelper environmentHelper) { if (string.IsNullOrWhiteSpace(folderPath)) @@ -82,8 +92,8 @@ public void ValidateFolderPath(string folderPath, IEnvironmentHelper environment /// /// Zip Files To Target Directory /// - /// - /// bool + /// The target directory to create a zip file from. + /// True if the zip operation succeeded; otherwise, false. public bool ZipFileToTargetDirectory(string targetDirectory) { Logger.Debug("FolderAction.ZipFileToTargetDirectory(): Start zipping directory."); @@ -126,6 +136,11 @@ public bool ZipFileToTargetDirectory(string targetDirectory) return isZiped; } + /// + /// Recursively copies all files and subdirectories from source to target directory. + /// + /// The source directory information. + /// The target directory information. private static void CopyAll(DirectoryInfo source, DirectoryInfo target) { Logger.DebugFormat("FolderAction.CopyAll(): Start copying from '{0}' to '{1}'.", source.FullName, target.FullName); @@ -165,5 +180,7 @@ private static void CopyAll(DirectoryInfo source, DirectoryInfo target) } Logger.DebugFormat("FolderAction.CopyAll(): Finished copying from '{0}' to '{1}'.", source.FullName, target.FullName); } + + #endregion } } diff --git a/src/LCT.Common/Interface/IChecker.cs b/src/LCT.Common/Interface/IChecker.cs index 56e45159d..68914c365 100644 --- a/src/LCT.Common/Interface/IChecker.cs +++ b/src/LCT.Common/Interface/IChecker.cs @@ -13,10 +13,25 @@ namespace LCT.Common.Interface { public interface IChecker : IPrintRecommendation, IPrintWarning { + /// + /// Asynchronously loads compliance settings from the specified JSON file. + /// + /// The path to the JSON file containing compliance settings. + /// A task that represents the asynchronous operation. The task result contains the loaded ComplianceSettingsModel. Task LoadSettingsAsync(string jsonFilePath); + /// + /// Checks the provided data against the specified compliance settings. + /// + /// The compliance settings to use for validation. + /// The data to check for compliance. + /// True if the data is compliant; otherwise, false. bool Check(ComplianceSettingsModel settings, Object data); + /// + /// Gets the results of the compliance checks. + /// + /// A list of result strings. List GetResults(); } } diff --git a/src/LCT.Common/Interface/ICycloneDXBomParser.cs b/src/LCT.Common/Interface/ICycloneDXBomParser.cs index 9313d0c35..82ac6bf76 100644 --- a/src/LCT.Common/Interface/ICycloneDXBomParser.cs +++ b/src/LCT.Common/Interface/ICycloneDXBomParser.cs @@ -13,6 +13,11 @@ namespace LCT.Common /// public interface ICycloneDXBomParser { + /// + /// Parses a CycloneDX BOM file and returns a Bom object. + /// + /// The path to the CycloneDX BOM file. + /// The parsed Bom object. public Bom ParseCycloneDXBom(string filePath); } diff --git a/src/LCT.Common/Interface/IEnvironmentHelper.cs b/src/LCT.Common/Interface/IEnvironmentHelper.cs index f32ba373f..e37f9d69f 100644 --- a/src/LCT.Common/Interface/IEnvironmentHelper.cs +++ b/src/LCT.Common/Interface/IEnvironmentHelper.cs @@ -8,6 +8,11 @@ namespace LCT.Common.Interface { public interface IEnvironmentHelper { + /// + /// Calls Environment.Exit with the specified exit code. + /// + /// The exit code to use when terminating the process. + /// void. void CallEnvironmentExit(int exitCode); } diff --git a/src/LCT.Common/Interface/IFileOperations.cs b/src/LCT.Common/Interface/IFileOperations.cs index 6f9b9e95d..0c3a56616 100644 --- a/src/LCT.Common/Interface/IFileOperations.cs +++ b/src/LCT.Common/Interface/IFileOperations.cs @@ -14,58 +14,72 @@ namespace LCT.Common.Interface public interface IFileOperations { /// - /// Writes the given content to the file + /// Writes the given content to a file in the specified folder. /// - /// Any type - /// Data to write - /// Folder path to save the file - /// File Name with Extension + /// The type of data to write. + /// The data to write. + /// The folder path to save the file. + /// The file name with extension. + /// The project name associated with the file. + /// The path to the written file. public string WriteContentToFile(T dataToWrite, string folderPath, string fileNameWithExtension, string projectName); + /// - /// Writes the given content to the file + /// Writes the given content to an output BOM file in the specified folder. /// - /// Any type - /// Data to write - /// Folder path to save the file - /// File Name with Extension + /// The type of data to write. + /// The data to write. + /// The folder path to save the file. + /// The file name with extension. + /// The project name associated with the file. + /// The path to the written BOM file. public string WriteContentToOutputBomFile(T dataToWrite, string folderPath, string fileNameWithExtension, string projectName); /// - /// Validatest the given file path + /// Validates the given file path. /// - /// filePath + /// The file path to validate. + /// void. public void ValidateFilePath(string filePath); /// - /// combines the comparisonBom data + /// Combines components from an existing BOM file. /// - /// comparisonBOM data - /// filePath + /// The BOM components to combine. + /// The file path of the existing BOM. + /// The combined BOM object. public Bom CombineComponentsFromExistingBOM(Bom components, string filePath); /// - /// writes to existing cycloneDx bom + /// Writes the given content to an existing CycloneDX BOM file. /// - /// comparisonBOM data - /// filePath + /// The type of data to write. + /// The BOM data to write. + /// The file path of the CycloneDX BOM. + /// The file name with extension. + /// The path to the written CycloneDX BOM file. public string WriteContentToCycloneDXFile(T dataToWrite, string filePath, string fileNameWithExtension); /// - /// Writes the given content to the file + /// Writes the given content to a report file for not approved items. /// - /// Any type - /// Data to write - /// Folder path to save the file - /// File Name with Extension + /// The type of data to write. + /// The data to write. + /// The folder path to save the file. + /// The file name with extension. + /// The name associated with the report. + /// The path to the written report file. public string WriteContentToReportNotApprovedFile(T dataToWrite, string folderPath, string fileNameWithExtension, string name); /// - /// Writes the given content to the file + /// Writes the given content to a file for multiple versions in the specified folder. /// - /// Any type - /// Data to write - /// Folder path to save the file - /// File Name with Extension + /// The type of data to write. + /// The data to write. + /// The folder path to save the file. + /// The file name with extension. + /// The project name associated with the file. + /// The path to the written file for multiple versions. public string WriteContentToMultipleVersionsFile(T dataToWrite, string folderPath, string fileNameWithExtension, string projectName); } } diff --git a/src/LCT.Common/Interface/IFileParser.cs b/src/LCT.Common/Interface/IFileParser.cs index fbbe8e426..becc0ce8a 100644 --- a/src/LCT.Common/Interface/IFileParser.cs +++ b/src/LCT.Common/Interface/IFileParser.cs @@ -10,6 +10,11 @@ namespace LCT.Common.Interface { internal interface IFileParser { + /// + /// Parses a TOML file and returns its contents as a TomlTable. + /// + /// The path to the TOML file. + /// The parsed TOML table. public TomlTable ParseTomlFile(string filePath); } } diff --git a/src/LCT.Common/Interface/IFolderAction.cs b/src/LCT.Common/Interface/IFolderAction.cs index 8b219bf65..7309888cc 100644 --- a/src/LCT.Common/Interface/IFolderAction.cs +++ b/src/LCT.Common/Interface/IFolderAction.cs @@ -12,22 +12,22 @@ namespace LCT.Common.Interface public interface IFolderAction { /// - /// Copies source directory content to target directory content + /// Copies the contents of the source directory to the target directory. /// - /// - /// - /// bool + /// The path of the source directory. + /// The path of the target directory. + /// True if the copy was successful; otherwise, false. public bool CopyToTargetDirectory(string sourceDirectory, string targetDirectory); /// - /// Zip Files To Target Directory + /// Zips files to the specified target directory. /// - /// - /// bool + /// The path of the target directory where files will be zipped. + /// True if the zip operation was successful; otherwise, false. public bool ZipFileToTargetDirectory(string targetDirectory); /// - /// Validates the given folder path + /// Validates the given folder path. /// /// public void ValidateFolderPath(string folderPath, IEnvironmentHelper environmentHelper); diff --git a/src/LCT.Common/Interface/IPrintRecommendation.cs b/src/LCT.Common/Interface/IPrintRecommendation.cs index f39152869..37c5195cd 100644 --- a/src/LCT.Common/Interface/IPrintRecommendation.cs +++ b/src/LCT.Common/Interface/IPrintRecommendation.cs @@ -11,7 +11,8 @@ public interface IPrintRecommendation /// /// Prints a specific recommendation message. /// - /// param name="content">The content of the recommendation message to be printed. + /// The content of the recommendation message to be printed. + /// void. void PrintRecommendation(string content); } } diff --git a/src/LCT.Common/Interface/IPrintWarning.cs b/src/LCT.Common/Interface/IPrintWarning.cs index 1e7e4da32..ef651c8a9 100644 --- a/src/LCT.Common/Interface/IPrintWarning.cs +++ b/src/LCT.Common/Interface/IPrintWarning.cs @@ -12,6 +12,7 @@ public interface IPrintWarning /// Prints a warning message to the output. /// /// The warning message to be displayed. Cannot be null or empty. + /// void. void PrintWarning(string content); } } diff --git a/src/LCT.Common/Interface/ISettingsManager.cs b/src/LCT.Common/Interface/ISettingsManager.cs index b5bf301e3..41ca6b3a0 100644 --- a/src/LCT.Common/Interface/ISettingsManager.cs +++ b/src/LCT.Common/Interface/ISettingsManager.cs @@ -12,13 +12,19 @@ namespace LCT.Common.Interface public interface ISettingsManager { /// - /// Reads the Configuration from input args and json setting file + /// Reads the configuration from input arguments and a JSON settings file. /// - /// args - /// jsonSettingsFileName - /// AppSettings + /// The command-line arguments. + /// The name of the JSON settings file. + /// The environment helper for system interactions. + /// An instance of the application settings type T. public T ReadConfiguration(string[] args, string jsonSettingsFileName, IEnvironmentHelper environmentHelper); + /// + /// Checks that all required arguments are present to run the application. + /// + /// The application settings object. + /// The name of the current executable. public void CheckRequiredArgsToRun(CommonAppSettings appSettings, string currentExe); } } diff --git a/src/LCT.Common/Interface/ISpdxBomParser.cs b/src/LCT.Common/Interface/ISpdxBomParser.cs index 514706882..721a1e514 100644 --- a/src/LCT.Common/Interface/ISpdxBomParser.cs +++ b/src/LCT.Common/Interface/ISpdxBomParser.cs @@ -12,6 +12,11 @@ namespace LCT.Common.Interface { public interface ISpdxBomParser { + /// + /// Parses an SPDX BOM file and returns a Bom object. + /// + /// The path to the SPDX BOM file. + /// The parsed Bom object. public Bom ParseSPDXBom(string filePath); } } diff --git a/src/LCT.Common/Logging/Log4net.cs b/src/LCT.Common/Logging/Log4net.cs index c47d04ba5..f01147951 100644 --- a/src/LCT.Common/Logging/Log4net.cs +++ b/src/LCT.Common/Logging/Log4net.cs @@ -22,12 +22,41 @@ namespace LCT.Common /// public static class Log4Net { + #region Fields + // No fields present. + #endregion + + #region Properties + /// + /// Gets or sets the logger repository. + /// public static ILoggerRepository LoggerRepository { get; set; } + /// + /// Gets or sets the path to the log file. + /// public static string CatoolLogPath { get; set; } + + /// + /// Gets or sets the current directory for the tool. + /// public static string CatoolCurrentDirectory { get; set; } public static bool Verbose { get; set; } + #endregion Properties + + #region Constructors + // No constructors present. + #endregion + + #region Methods + /// + /// Initializes the log4net logger with the specified log file name, folder, and verbosity. + /// + /// The name of the log file. + /// The folder where the log file will be stored. + /// If true, sets verbose logging level. + /// void. public static void Init(string logFileName, string logFolder, bool verbose) { LoggerRepository = LogManager.GetRepository(Assembly.GetEntryAssembly()); @@ -50,6 +79,13 @@ public static void Init(string logFileName, string logFolder, bool verbose) } } + /// + /// Activates the file appender for logging, setting verbosity and log path. + /// + /// If true, sets verbose logging level. + /// The path to the log file. + /// The array of appenders to configure. + /// void. public static void ActivateFileAppender(bool verbose, string logPath, IAppender[] appenders) { foreach (IAppender appender in appenders) @@ -67,6 +103,10 @@ public static void ActivateFileAppender(bool verbose, string logPath, IAppender[ } } + /// + /// Gets the default log4net configuration file path based on the environment. + /// + /// The path to the default log4net config file. public static string GetDefaultLogConfigFile() { EnvironmentType envType = RuntimeEnvironment.GetEnvironment(); @@ -90,6 +130,8 @@ public static void AppendVerboseValue(CommonAppSettings appSettings) Verbose = false; } } + + #endregion Methods } } diff --git a/src/LCT.Common/Logging/LoggerFactory.cs b/src/LCT.Common/Logging/LoggerFactory.cs index f8e399643..6260547a1 100644 --- a/src/LCT.Common/Logging/LoggerFactory.cs +++ b/src/LCT.Common/Logging/LoggerFactory.cs @@ -11,9 +11,27 @@ namespace LCT.Common { public static class LoggerFactory { - // This property determines whether to use Spectre.Console for logging or log4net. + #region Fields + // No fields present. + #endregion + + #region Properties + /// + /// Determines whether to use Spectre.Console for logging or log4net. + /// public static bool UseSpectreConsole { get; set; } = true; + #endregion + + #region Constructors + // No constructors present. + #endregion + #region Methods + /// + /// Gets a logger for the specified type. + /// + /// The type for which to get the logger. + /// An ILog instance for the specified type. public static ILog GetLogger(System.Type type) { if (UseSpectreConsole) @@ -22,6 +40,11 @@ public static ILog GetLogger(System.Type type) return LogManager.GetLogger(type); } + /// + /// Gets a logger for the specified method. + /// + /// The method for which to get the logger. + /// An ILog instance for the method's declaring type. public static ILog GetLogger(MethodBase method) { if (UseSpectreConsole) @@ -29,5 +52,10 @@ public static ILog GetLogger(MethodBase method) else return LogManager.GetLogger(method.DeclaringType); } + #endregion + + #region Events + // No events present. + #endregion } } \ No newline at end of file diff --git a/src/LCT.Common/Logging/LoggerHelper.cs b/src/LCT.Common/Logging/LoggerHelper.cs index bbcd9b343..5b8969b67 100644 --- a/src/LCT.Common/Logging/LoggerHelper.cs +++ b/src/LCT.Common/Logging/LoggerHelper.cs @@ -19,18 +19,29 @@ namespace LCT.Common.Logging { + /// + /// Provides helper methods for logging with Spectre.Console integration and fallback support. + /// public static class LoggerHelper { - static readonly ILog Logger = LoggerFactory.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + #region Fields + static readonly ILog Logger = LoggerFactory.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static IAnsiConsole _console; private static readonly object _consoleLock = new(); - - // Constants for repeated string literals private const string AlertConstant = "Alert"; private const string BlueVersionMarkup = "[blue]Version[/]"; private const string GreenNameMarkup = "[green]Name[/]"; + private static readonly Dictionary _colorCache = new Dictionary(); + private static int _colorIndex = 0; + + #endregion + #region Properties + + /// + /// Gets the singleton Spectre.Console instance with thread-safe initialization. + /// public static IAnsiConsole ConsoleInstance { get @@ -49,6 +60,15 @@ public static IAnsiConsole ConsoleInstance return _console; } } + + #endregion + + #region Methods + + /// + /// Gets the automatic console width based on the current environment. + /// + /// The console width in characters. private static int GetAutoConsoleWidth() { @@ -68,6 +88,11 @@ ex is System.IO.IOException || return 200; } } + + /// + /// Builds ANSI console settings based on the runtime environment. + /// + /// The configured ANSI console settings. private static AnsiConsoleSettings BuildAnsiConsoleSettings() { EnvironmentType envType = RuntimeEnvironment.GetEnvironment(); @@ -83,6 +108,12 @@ private static AnsiConsoleSettings BuildAnsiConsoleSettings() }; return settings; } + + /// + /// Gets the color system support based on the environment type. + /// + /// The environment type. + /// The color system support level. private static ColorSystemSupport GetColorSystem(EnvironmentType envType) { // User override @@ -105,15 +136,21 @@ private static ColorSystemSupport GetColorSystem(EnvironmentType envType) return ColorSystemSupport.TrueColor; } - // Wrapper helper so existing code only changes AnsiConsole.* to ConsoleInstance.* + /// + /// Wraps a console write action for consistent console instance usage. + /// + /// The write action to execute. private static void ConsoleWrite(Action writeAction) { writeAction(ConsoleInstance); } - private static readonly Dictionary _colorCache = new Dictionary(); - private static int _colorIndex = 0; - + /// + /// Executes a Spectre.Console action with exception handling and fallback logging. + /// + /// The Spectre action to execute. + /// The fallback message to log if the action fails. + /// The type of fallback message. public static void SafeSpectreAction(Action spectreAction, string fallbackMessage, string fallbackType = "Info") { try @@ -133,6 +170,14 @@ ex is NotSupportedException Logger.Debug($"SafeSpectreAction suppressed exception: {ex.GetType().Name} - {ex.Message}"); } } + + /// + /// Writes components without download URL using Spectre.Console tables for KPI display. + /// + /// The list of components without download URLs. + /// The list of releases not created. + /// The SW360 base URL. + /// The list of duplicate components by PURL ID. public static void WriteComponentsWithoutDownloadURLByUseingSpectreToKpi(List componentInfo, List lstReleaseNotCreated, string sw360URL, List duplicateComponentsByPurlId) { if (componentInfo.Count > 0 || lstReleaseNotCreated.Count > 0 || duplicateComponentsByPurlId.Count > 0) @@ -151,6 +196,12 @@ public static void WriteComponentsWithoutDownloadURLByUseingSpectreToKpi(List + /// Displays duplicate components by PURL ID in a formatted table. + /// + /// The list of duplicate components. + /// The SW360 base URL. private static void DisplayDuplicateComponentsByPurlId(List duplicateComponents, string sw360URL) { if (duplicateComponents == null || duplicateComponents.Count == 0) @@ -193,6 +244,12 @@ private static void DisplayDuplicateComponentsByPurlId(List duplicat ConsoleInstance.Write(table); WriteLine(); } + + /// + /// Displays components without source URLs in a formatted table. + /// + /// The list of components without URLs. + /// The SW360 base URL. private static void DisplayComponentsWithoutUrl(List componentInfo, string sw360URL) { if (componentInfo.Count <= 0) return; @@ -209,6 +266,10 @@ private static void DisplayComponentsWithoutUrl(List componen WriteLine(); } + /// + /// Displays components that were not created in SW360 in a formatted table. + /// + /// The list of components not created. private static void DisplayNotCreatedComponents(List lstReleaseNotCreated) { if (lstReleaseNotCreated.Count <= 0) return; @@ -225,6 +286,11 @@ private static void DisplayNotCreatedComponents(List lstReleaseNotCr WriteLine(); } + /// + /// Creates a component table with specified columns. + /// + /// Whether to include a URL column. + /// The configured table. private static Table CreateComponentTable(bool includeUrl) { var table = new Table() @@ -248,6 +314,12 @@ private static Table CreateComponentTable(bool includeUrl) } + /// + /// Populates a component info table with data. + /// + /// The table to populate. + /// The component information. + /// The SW360 base URL. private static void PopulateComponentInfoTable(Table table, List componentInfo, string sw360URL) { foreach (var item in componentInfo) @@ -261,6 +333,11 @@ private static void PopulateComponentInfoTable(Table table, List + /// Populates a table with components that were not created. + /// + /// The table to populate. + /// The list of components. private static void PopulateNotCreatedComponentsTable(Table table, List components) { foreach (var item in components) @@ -271,6 +348,11 @@ private static void PopulateNotCreatedComponentsTable(Table table, List + /// Writes a table of components not linked to project using Spectre.Console. + /// + /// The list of unlinked components. public static void WriteComponentsNotLinkedListTableWithSpectre(List components) { if (components.Count > 0) @@ -315,6 +397,11 @@ public static void WriteComponentsNotLinkedListTableWithSpectre(List }, "Components Not Linked", AlertConstant); } } + + /// + /// Writes components not linked to project in console using log4net. + /// + /// The list of unlinked components. public static void WriteComponentsNotLinkedListInConsole(List components) { if (LoggerFactory.UseSpectreConsole) @@ -344,6 +431,13 @@ public static void WriteComponentsNotLinkedListInConsole(List compon } } + /// + /// Writes components without download URL to KPI using either Spectre or log4net. + /// + /// The list of components without download URLs. + /// The list of releases not created. + /// The SW360 base URL. + /// The list of duplicate components by PURL ID. public static void WriteComponentsWithoutDownloadURLToKpi(List componentInfo, List lstReleaseNotCreated, string sw360URL, List DuplicateComponentsByPurlId) { if (LoggerFactory.UseSpectreConsole) @@ -398,6 +492,12 @@ public static void WriteComponentsWithoutDownloadURLToKpi(List + /// Displays all application settings for the detected project types. + /// + /// The list of components in the BOM. + /// The application settings. public static void DisplayAllSettings(List componentsInBOM, CommonAppSettings appSettings) { var projectTypes = GetProjectTypes(componentsInBOM); @@ -413,6 +513,11 @@ public static void DisplayAllSettings(List componentsInBOM, CommonApp } } + /// + /// Gets the list of project types from the components in the BOM. + /// + /// The list of components. + /// The list of unique project types. private static List GetProjectTypes(List componentsInBOM) { if (componentsInBOM == null || componentsInBOM.Count == 0) @@ -426,6 +531,11 @@ private static List GetProjectTypes(List componentsInBOM) .Distinct(StringComparer.OrdinalIgnoreCase)]; } + /// + /// Creates a dictionary mapping project types to their configurations. + /// + /// The application settings. + /// The project configuration map. private static Dictionary CreateProjectConfigMap(CommonAppSettings appSettings) { return new Dictionary(StringComparer.OrdinalIgnoreCase) @@ -441,6 +551,11 @@ private static Dictionary CreateProjectConfigMap(CommonAppSettin }; } + /// + /// Displays settings using Spectre.Console formatting. + /// + /// The list of project types. + /// The project configuration map. private static void DisplaySettingsWithSpectre(List projectTypes, Dictionary projectConfigMap) { SafeSpectreAction(() => @@ -457,6 +572,12 @@ private static void DisplaySettingsWithSpectre(List projectTypes, Dictio }, "Current Application Settings", "Info"); } + /// + /// Appends project type-specific settings to the content builder. + /// + /// The string builder. + /// The project type. + /// The project configuration map. private static void AppendProjectTypeSettings(StringBuilder content, string projectType, Dictionary projectConfigMap) { content.AppendLine($"[green]-[/] [green]{projectType}[/]\n"); @@ -474,12 +595,22 @@ private static void AppendProjectTypeSettings(StringBuilder content, string proj } } + /// + /// Appends configuration settings to the content builder. + /// + /// The string builder. + /// The configuration. private static void AppendConfigSettings(StringBuilder content, Config config) { AppendRepoSettings(content, config); AppendIncludeExcludeSettings(content, config); } + /// + /// Appends repository settings to the content builder. + /// + /// The string builder. + /// The configuration. private static void AppendRepoSettings(StringBuilder content, Config config) { content @@ -492,12 +623,22 @@ private static void AppendRepoSettings(StringBuilder content, Config config) .AppendLine($" [cyan]Config[/]"); } + /// + /// Gets the third-party repository name from configuration. + /// + /// The configuration. + /// The third-party repository name. private static string GetThirdPartyRepoName(Config config) { return config.Artifactory?.ThirdPartyRepos? .FirstOrDefault(repo => repo.Upload)?.Name ?? Dataconstant.NotConfigured; } + /// + /// Appends include and exclude settings to the content builder. + /// + /// The string builder. + /// The configuration. private static void AppendIncludeExcludeSettings(StringBuilder content, Config config) { var excludeList = GetFormattedList(config.Exclude); @@ -510,6 +651,11 @@ private static void AppendIncludeExcludeSettings(StringBuilder content, Config c .AppendLine($" └──> {excludeList}\n"); } + /// + /// Gets a formatted list from string array. + /// + /// The items array. + /// The formatted list string. private static string GetFormattedList(string[] items) { return !string.IsNullOrEmpty(items?.FirstOrDefault()) @@ -517,6 +663,11 @@ private static string GetFormattedList(string[] items) : Dataconstant.NotConfigured; } + /// + /// Displays settings using log4net logger. + /// + /// The list of project types. + /// The project configuration map. private static void DisplaySettingsWithLogger(List projectTypes, Dictionary projectConfigMap) { Logger.Info("Current Application Settings:"); @@ -535,6 +686,11 @@ private static void DisplaySettingsWithLogger(List projectTypes, Diction } } } + + /// + /// Displays package settings using log4net logger. + /// + /// The project configuration. private static void DisplayPackageSettings(Config project) { if (project == null) @@ -572,12 +728,24 @@ private static void DisplayPackageSettings(Config project) $"\t\tExclude:\t\t{excludeList}\n" + $"\t\tInclude:\t\t{includeList}\n", null); } + /// + /// Displays input parameters using Spectre.Console. + /// + /// The CA tool information. + /// The application settings. + /// The list of parameters for CLI. + /// The execution type. + /// The BOM file path. public static void DisplayInputParametersWithSpectreConsole(CatoolInfo caToolInformation, CommonAppSettings appSettings, ListofPerametersForCli listofPerameters, string exeType, string bomFilePath) { string content = GenerateContentByExeType(caToolInformation, appSettings, listofPerameters, exeType, bomFilePath); InitialDataPanel(content); } + /// + /// Displays initial data panel with formatted content. + /// + /// The content to display. public static void InitialDataPanel(string content) { SafeSpectreAction(() => @@ -598,6 +766,15 @@ public static void InitialDataPanel(string content) }, "Input Parameters", "Panel"); } + /// + /// Generates content based on execution type. + /// + /// The CA tool information. + /// The application settings. + /// The list of parameters for CLI. + /// The execution type. + /// The BOM file path. + /// The generated content string. private static string GenerateContentByExeType(CatoolInfo caToolInformation, CommonAppSettings appSettings, ListofPerametersForCli listofPerameters, string exeType, string bomFilePath) { @@ -610,6 +787,12 @@ private static string GenerateContentByExeType(CatoolInfo caToolInformation, Com }; } + /// + /// Appends directory information to the content builder. + /// + /// The string builder. + /// The application settings. + /// The maximum path length for wrapping. private static void AppendDirectoryInfo(StringBuilder content, CommonAppSettings appSettings, int maxPathLength) { content @@ -619,6 +802,12 @@ private static void AppendDirectoryInfo(StringBuilder content, CommonAppSettings .Append($" └──> {WrapPath(appSettings.Directory.OutputFolder, maxPathLength)}\n\n"); } + /// + /// Appends basic information to the content builder. + /// + /// The string builder. + /// The CA tool information. + /// The maximum path length for wrapping. private static void AppendBasicInfo(StringBuilder content, CatoolInfo caToolInformation, int maxPathLength) { content @@ -628,6 +817,13 @@ private static void AppendBasicInfo(StringBuilder content, CatoolInfo caToolInfo .Append($" └──> {WrapPath(caToolInformation.CatoolRunningLocation, maxPathLength)}\n\n"); } + /// + /// Appends SW360 information to the content builder. + /// + /// The string builder. + /// The application settings. + /// The list of parameters for CLI. + /// The maximum path length for wrapping. private static void AppendSw360Info(StringBuilder content, CommonAppSettings appSettings, ListofPerametersForCli listofPerameters, int maxPathLength) { @@ -642,6 +838,13 @@ private static void AppendSw360Info(StringBuilder content, CommonAppSettings app .Append($" └──> {WrapPath(string.IsNullOrEmpty(listofPerameters.ExcludeComponents) ? "None" : listofPerameters.ExcludeComponents, maxPathLength)}\n\n"); } + /// + /// Appends common information to the content builder. + /// + /// The string builder. + /// The application settings. + /// The list of parameters for CLI. + /// The maximum path length for wrapping. private static void AppendCommonInfo(StringBuilder content, CommonAppSettings appSettings, ListofPerametersForCli listofPerameters, int maxPathLength) { @@ -656,6 +859,13 @@ private static void AppendCommonInfo(StringBuilder content, CommonAppSettings ap .Append($" └──> {WrapPath(string.IsNullOrEmpty(listofPerameters.Exclude) ? "None" : listofPerameters.Exclude, maxPathLength)}"); } + /// + /// Generates identifier content for display. + /// + /// The CA tool information. + /// The application settings. + /// The list of parameters for CLI. + /// The generated identifier content string. private static string GenerateIdentifierContent(CatoolInfo caToolInformation, CommonAppSettings appSettings, ListofPerametersForCli listofPerameters) { @@ -693,6 +903,13 @@ private static string GenerateIdentifierContent(CatoolInfo caToolInformation, Co return content.ToString(); } + /// + /// Generates creator content for display. + /// + /// The CA tool information. + /// The application settings. + /// The BOM file path. + /// The generated creator content string. private static string GenerateCreatorContent(CatoolInfo caToolInformation, CommonAppSettings appSettings, string bomFilePath) { int consoleWidth = GetAutoConsoleWidth(); @@ -709,6 +926,13 @@ private static string GenerateCreatorContent(CatoolInfo caToolInformation, Commo return content.ToString(); } + /// + /// Generates uploader content for display. + /// + /// The CA tool information. + /// The application settings. + /// The BOM file path. + /// The generated uploader content string. private static string GenerateUploaderContent(CatoolInfo caToolInformation, CommonAppSettings appSettings, string bomFilePath) { int consoleWidth = GetAutoConsoleWidth(); @@ -725,6 +949,13 @@ private static string GenerateUploaderContent(CatoolInfo caToolInformation, Comm return content.ToString(); } + /// + /// Appends creator-specific information to the content builder. + /// + /// The string builder. + /// The application settings. + /// The BOM file path. + /// The maximum path length for wrapping. private static void AppendCreatorSpecificInfo(StringBuilder content, CommonAppSettings appSettings, string bomFilePath, int maxPathLength) { @@ -754,6 +985,13 @@ private static void AppendCreatorSpecificInfo(StringBuilder content, CommonAppSe } + /// + /// Appends uploader-specific information to the content builder. + /// + /// The string builder. + /// The application settings. + /// The BOM file path. + /// The maximum path length for wrapping. private static void AppendUploaderSpecificInfo(StringBuilder content, CommonAppSettings appSettings, string bomFilePath, int maxPathLength) { @@ -767,6 +1005,14 @@ private static void AppendUploaderSpecificInfo(StringBuilder content, CommonAppS .Append($"[green]-[/] [cyan]Log FolderPath[/]\n") .Append($" └──> {WrapPath(Log4Net.CatoolLogPath, maxPathLength)}"); } + /// + /// Logs input parameters using appropriate logging mechanism. + /// + /// The CA tool information. + /// The application settings. + /// The list of parameters for CLI. + /// The execution type. + /// The BOM file path. public static void LogInputParameters(CatoolInfo caToolInformation, CommonAppSettings appSettings, ListofPerametersForCli listofPerameters, string exeType = null, string bomFilePath = null) { @@ -779,6 +1025,14 @@ public static void LogInputParameters(CatoolInfo caToolInformation, CommonAppSet LogInputParametersWithLog4net(caToolInformation, appSettings, listofPerameters, exeType, bomFilePath); } } + /// + /// Logs input parameters using log4net logger. + /// + /// The CA tool information. + /// The application settings. + /// The list of parameters for CLI. + /// The execution type. + /// The BOM file path. private static void LogInputParametersWithLog4net(CatoolInfo caToolInformation, CommonAppSettings appSettings, ListofPerametersForCli listofPerameters, string exeType, string bomFilePath) { if (exeType == Dataconstant.Identifier) @@ -843,6 +1097,13 @@ private static void LogInputParametersWithLog4net(CatoolInfo caToolInformation, $"Log FolderPath:\t\t {Log4Net.CatoolLogPath}\n", null); } } + /// + /// Wraps a path string to fit within the specified maximum length. + /// + /// The path to wrap. + /// The maximum length per line. + /// The prefix to add to wrapped lines. + /// The wrapped path string. public static string WrapPath(string path, int maxLength = 80, string prefix = " ") { if (string.IsNullOrEmpty(path) || path.Length <= maxLength) @@ -872,6 +1133,13 @@ public static string WrapPath(string path, int maxLength = 80, string prefix = " return string.Join($"\n{prefix}", lines); } + /// + /// Writes a styled panel with content using Spectre.Console. + /// + /// The content to display. + /// The optional panel title. + /// The border style. + /// The header style. public static void WriteStyledPanel(string content, string title = null, string borderStyle = "white", string headerStyle = "yellow") { SafeSpectreAction(() => @@ -896,6 +1164,10 @@ public static void WriteStyledPanel(string content, string title = null, string ConsoleWrite(c => c.Write(panel)); }, content, title ?? "Panel"); } + /// + /// Writes a summary header with centered title. + /// + /// The header title. public static void WriteSummaryHeader(string title) { SafeSpectreAction(() => @@ -915,6 +1187,10 @@ public static void WriteSummaryHeader(string title) }); }, title, "Header"); } + /// + /// Writes a header with title. + /// + /// The header title. public static void WriteHeader(string title) { SafeSpectreAction(() => @@ -925,6 +1201,11 @@ public static void WriteHeader(string title) }, title, "Header"); } + /// + /// Writes a fallback message using log4net when Spectre.Console is not available. + /// + /// The message to write. + /// The message type. public static void WriteFallback(string message, string messageType = "Info") { string prefix = messageType.ToLower() switch @@ -954,6 +1235,14 @@ public static void WriteFallback(string message, string messageType = "Info") break; } } + /// + /// Writes data to console table using appropriate logging mechanism. + /// + /// The data to print. + /// The timing data to print. + /// The project summary link. + /// The execution type. + /// The KPI names. public static void WriteToConsoleTable(Dictionary printData, Dictionary printTimingData, string ProjectSummaryLink, string exeType, KpiNames KpiNames) { if (LoggerFactory.UseSpectreConsole) @@ -987,6 +1276,11 @@ public static void WriteToConsoleTable(Dictionary printData, Dictio } } + /// + /// Logs a table row with separator. + /// + /// The row key. + /// The row value. private static void LogTableRow(string key, int value) { string row = $"{"|",5}{key,-70} {"|",5} {value,5} {"|",5}"; @@ -1004,6 +1298,14 @@ private static void LogTableRow(string key, int value) } } + /// + /// Writes data to console table using Spectre.Console formatting. + /// + /// The data to print. + /// The timing data to print. + /// The project summary link. + /// The execution type. + /// The KPI names. public static void WriteToSpectreConsoleTable( Dictionary printData, Dictionary printTimingData, @@ -1030,6 +1332,10 @@ public static void WriteToSpectreConsoleTable( }, "Package Summary Table", "Panel"); } + /// + /// Writes project summary link if available. + /// + /// The project summary link. private static void WriteProjectSummary(string projectSummaryLink) { if (!string.IsNullOrWhiteSpace(projectSummaryLink)) @@ -1039,6 +1345,11 @@ private static void WriteProjectSummary(string projectSummaryLink) } } + /// + /// Creates a summary table with configured columns. + /// + /// The console width. + /// The configured table instance. private static Table CreateSummaryTable(int consoleWidth) { var table = new Table() @@ -1053,6 +1364,14 @@ private static Table CreateSummaryTable(int consoleWidth) return table; } + /// + /// Adds summary rows to the table with visual bars. + /// + /// The table instance. + /// The data to add. + /// The maximum value for bar scaling. + /// The maximum bar width. + /// The KPI names. private static void AddSummaryRows( Table table, Dictionary printData, @@ -1075,6 +1394,10 @@ private static void AddSummaryRows( + /// + /// Writes timing data to console. + /// + /// The timing data to write. private static void WriteTimingData(Dictionary printTimingData) { if (printTimingData.Count == 0) @@ -1089,6 +1412,13 @@ private static void WriteTimingData(Dictionary printTimingData) WriteLine(); } + /// + /// Gets the appropriate color for a KPI item based on its key and value. + /// + /// The item key. + /// The item value. + /// The KPI names configuration. + /// The color string for the item. private static string GetColorForItem(string key, int value, KpiNames kpiNames) { if (string.IsNullOrWhiteSpace(key) || kpiNames == null) @@ -1168,6 +1498,10 @@ private static string GetColorForItem(string key, int value, KpiNames kpiNames) _colorIndex++; return assigned; } + /// + /// Writes internal components table to CLI using appropriate logging mechanism. + /// + /// The list of internal components. public static void WriteInternalComponentsTableInCli(List internalComponents) { if (LoggerFactory.UseSpectreConsole) @@ -1180,6 +1514,10 @@ public static void WriteInternalComponentsTableInCli(List internalCom WriteInternalComponentsListToKpi(internalComponents); } } + /// + /// Writes internal components list table to KPI using Spectre.Console. + /// + /// The list of internal components. public static void WriteInternalComponentsListTableToKpi(List internalComponents) { if (internalComponents?.Count > 0) @@ -1217,6 +1555,10 @@ public static void WriteInternalComponentsListTableToKpi(List interna }, "* Internal Components Identified which will not be sent for clearing:", AlertConstant); } } + /// + /// Writes internal components list to KPI using log4net. + /// + /// The list of internal components. public static void WriteInternalComponentsListToKpi(List internalComponents) { const string Name = "Name"; @@ -1237,6 +1579,10 @@ public static void WriteInternalComponentsListToKpi(List internalComp Logger.Info("\n"); } } + /// + /// Writes a telemetry message using appropriate logging mechanism. + /// + /// The telemetry message. public static void WriteTelemetryMessage(string message) { if (LoggerFactory.UseSpectreConsole) @@ -1254,6 +1600,10 @@ public static void WriteTelemetryMessage(string message) Logger.Warn(message); } } + /// + /// Writes an initial message using Spectre.Console or log4net. + /// + /// The initial message. public static void SpectreConsoleInitialMessage(string message) { if (LoggerFactory.UseSpectreConsole) @@ -1267,6 +1617,10 @@ public static void SpectreConsoleInitialMessage(string message) } } + /// + /// Displays valid file information in CLI. + /// + /// The configuration file path. public static void ValidFilesInfoDisplayForCli(string configFile) { if (LoggerFactory.UseSpectreConsole) @@ -1279,6 +1633,9 @@ public static void ValidFilesInfoDisplayForCli(string configFile) } } + /// + /// Displays JFrog connection information in CLI. + /// public static void JfrogConnectionInfoDisplayForCli() { if (LoggerFactory.UseSpectreConsole) @@ -1291,15 +1648,27 @@ public static void JfrogConnectionInfoDisplayForCli() } } + /// + /// Writes a blank line to console. + /// public static void WriteLine() { SafeSpectreAction(() => ConsoleWrite(c => c.WriteLine()), "", "Info"); } + /// + /// Writes an info message with markup formatting. + /// + /// The message with markup. public static void WriteInfoWithMarkup(string message) { SafeSpectreAction(() => ConsoleWrite(c => c.MarkupLine(message)), message, "Info"); } + /// + /// Writes FOSSology process initialization message. + /// + /// The formatted component name. + /// The comparison BOM data item. public static void WriteFossologyProcessInitializeMessage(string formattedName, ComparisonBomData item) { if (LoggerFactory.UseSpectreConsole) @@ -1311,6 +1680,10 @@ public static void WriteFossologyProcessInitializeMessage(string formattedName, Logger.Logger.Log(null, Level.Notice, $"\tInitiating FOSSology process for: Release : Name - {formattedName} , version - {item.Version}", null); } } + /// + /// Writes FOSSology status message. + /// + /// The status message. public static void WriteFossologyStatusMessage(string message) { if (LoggerFactory.UseSpectreConsole) @@ -1323,6 +1696,10 @@ public static void WriteFossologyStatusMessage(string message) Logger.Warn($"\t{message}"); } } + /// + /// Writes FOSSology exception message. + /// + /// The exception message. public static void WriteFossologyExceptionMessage(string message) { if (LoggerFactory.UseSpectreConsole) @@ -1335,6 +1712,11 @@ public static void WriteFossologyExceptionMessage(string message) Logger.Error($"\t{message}"); } } + /// + /// Writes component status message. + /// + /// The status message. + /// The comparison BOM data item. public static void WriteComponentStatusMessage(string message, ComparisonBomData item) { if (LoggerFactory.UseSpectreConsole) @@ -1347,6 +1729,12 @@ public static void WriteComponentStatusMessage(string message, ComparisonBomData } } + /// + /// Writes FOSSology success status message. + /// + /// The success message. + /// The formatted component name. + /// The comparison BOM data item. public static void WriteFossologySucessStatusMessage(string message, string formattedName, ComparisonBomData item) { if (LoggerFactory.UseSpectreConsole) @@ -1358,6 +1746,11 @@ public static void WriteFossologySucessStatusMessage(string message, string form Logger.Logger.Log(null, Level.Info, $"\n{message} : Name - {formattedName}, version - {item.Version}", null); } } + /// + /// Displays MSBuild version information. + /// + /// The display message. + /// The version string. public static void MSBuildVersionDisplay(string message, string version) { if (LoggerFactory.UseSpectreConsole) @@ -1369,6 +1762,11 @@ public static void MSBuildVersionDisplay(string message, string version) Logger.Info($"{message}{version}"); } } + /// + /// Logs duplicate components by PURL ID using log4net. + /// + /// The list of duplicate components. + /// The SW360 base URL. private static void LogDuplicateComponentsByPurlId(List duplicateComponents, string sw360URL) { if (duplicateComponents.Count > 0) @@ -1399,6 +1797,7 @@ private static void LogDuplicateComponentsByPurlId(List duplicateCom } } + #endregion public static void WriteChocoManualStepsNotification(List components) { if (components == null || components.Count == 0) diff --git a/src/LCT.Common/Logging/SpectreLogAdapter.cs b/src/LCT.Common/Logging/SpectreLogAdapter.cs index 1a549d047..18a84261b 100644 --- a/src/LCT.Common/Logging/SpectreLogAdapter.cs +++ b/src/LCT.Common/Logging/SpectreLogAdapter.cs @@ -12,11 +12,24 @@ namespace LCT.Common { + /// + /// Adapter that integrates SpectreLogger with log4net's ILog interface for enhanced console logging. + /// public class SpectreLogAdapter : ILog { + #region Fields + private readonly SpectreLogger _logger; private readonly ILog _fileLogger; + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + /// The name of the logger. public SpectreLogAdapter(string loggerName) { string resolvedLoggerName = loggerName ?? "Unknown"; @@ -24,157 +37,345 @@ public SpectreLogAdapter(string loggerName) _fileLogger = LogManager.GetLogger(resolvedLoggerName); } + #endregion + + #region Properties + + /// + /// Gets a value indicating whether debug logging is enabled. + /// public bool IsDebugEnabled => true; + + /// + /// Gets a value indicating whether info logging is enabled. + /// public bool IsInfoEnabled => true; + + /// + /// Gets a value indicating whether warn logging is enabled. + /// public bool IsWarnEnabled => true; + + /// + /// Gets a value indicating whether error logging is enabled. + /// public bool IsErrorEnabled => true; + + /// + /// Gets a value indicating whether fatal logging is enabled. + /// public bool IsFatalEnabled => true; - // Return our own implementation of ILogger + /// + /// Gets the underlying logger instance. + /// public ILogger Logger => _logger; + #endregion + + #region Methods + #region Debug Methods + + /// + /// Logs a debug message. + /// + /// The message to log. public void Debug(object message) { _fileLogger.Debug(message); } + /// + /// Logs a debug message with an exception. + /// + /// The message to log. + /// The exception to log. public void Debug(object message, Exception exception) { _fileLogger.Debug(message); } + /// + /// Logs a formatted debug message. + /// + /// The format string. + /// The format arguments. public void DebugFormat(string format, params object[] args) { _logger.Log(null, Level.Debug, string.Format(CultureInfo.InvariantCulture, format, args), null); } + /// + /// Logs a formatted debug message with one argument. + /// + /// The format string. + /// The first format argument. public void DebugFormat(string format, object arg0) { _logger.Log(null, Level.Debug, string.Format(CultureInfo.InvariantCulture, format, arg0), null); } + /// + /// Logs a formatted debug message with two arguments. + /// + /// The format string. + /// The first format argument. + /// The second format argument. public void DebugFormat(string format, object arg0, object arg1) { _logger.Log(null, Level.Debug, string.Format(CultureInfo.InvariantCulture, format, arg0, arg1), null); } + /// + /// Logs a formatted debug message with three arguments. + /// + /// The format string. + /// The first format argument. + /// The second format argument. + /// The third format argument. public void DebugFormat(string format, object arg0, object arg1, object arg2) { _logger.Log(null, Level.Debug, string.Format(CultureInfo.InvariantCulture, format, arg0, arg1, arg2), null); } + /// + /// Logs a formatted debug message with a custom format provider. + /// + /// The format provider. + /// The format string. + /// The format arguments. public void DebugFormat(IFormatProvider provider, string format, params object[] args) { _logger.Log(null, Level.Debug, string.Format(provider, format, args), null); } + #endregion #region Info Methods + + /// + /// Logs an info message. + /// + /// The message to log. public void Info(object message) { _fileLogger.Info(message); } + /// + /// Logs an info message with an exception. + /// + /// The message to log. + /// The exception to log. public void Info(object message, Exception exception) { _fileLogger.Info(message); } + /// + /// Logs a formatted info message. + /// + /// The format string. + /// The format arguments. public void InfoFormat(string format, params object[] args) { _logger.Log(null, Level.Info, string.Format(CultureInfo.InvariantCulture, format, args), null); } + /// + /// Logs a formatted info message with one argument. + /// + /// The format string. + /// The first format argument. public void InfoFormat(string format, object arg0) { _logger.Log(null, Level.Info, string.Format(CultureInfo.InvariantCulture, format, arg0), null); } + /// + /// Logs a formatted info message with two arguments. + /// + /// The format string. + /// The first format argument. + /// The second format argument. public void InfoFormat(string format, object arg0, object arg1) { _logger.Log(null, Level.Info, string.Format(CultureInfo.InvariantCulture, format, arg0, arg1), null); } + /// + /// Logs a formatted info message with three arguments. + /// + /// The format string. + /// The first format argument. + /// The second format argument. + /// The third format argument. public void InfoFormat(string format, object arg0, object arg1, object arg2) { _logger.Log(null, Level.Info, string.Format(CultureInfo.InvariantCulture, format, arg0, arg1, arg2), null); } + /// + /// Logs a formatted info message with a custom format provider. + /// + /// The format provider. + /// The format string. + /// The format arguments. public void InfoFormat(IFormatProvider provider, string format, params object[] args) { _logger.Log(null, Level.Info, string.Format(provider, format, args), null); } + #endregion #region Warn Methods + + /// + /// Logs a warning message. + /// + /// The message to log. public void Warn(object message) { _fileLogger.Warn(message); } + /// + /// Logs a warning message with an exception. + /// + /// The message to log. + /// The exception to log. public void Warn(object message, Exception exception) { _fileLogger.Warn(message); } + /// + /// Logs a formatted warning message. + /// + /// The format string. + /// The format arguments. public void WarnFormat(string format, params object[] args) { _logger.Log(null, Level.Warn, string.Format(CultureInfo.InvariantCulture, format, args), null); } + /// + /// Logs a formatted warning message with one argument. + /// + /// The format string. + /// The first format argument. public void WarnFormat(string format, object arg0) { _logger.Log(null, Level.Warn, string.Format(CultureInfo.InvariantCulture, format, arg0), null); } + /// + /// Logs a formatted warning message with two arguments. + /// + /// The format string. + /// The first format argument. + /// The second format argument. public void WarnFormat(string format, object arg0, object arg1) { _logger.Log(null, Level.Warn, string.Format(CultureInfo.InvariantCulture, format, arg0, arg1), null); } + /// + /// Logs a formatted warning message with three arguments. + /// + /// The format string. + /// The first format argument. + /// The second format argument. + /// The third format argument. public void WarnFormat(string format, object arg0, object arg1, object arg2) { _logger.Log(null, Level.Warn, string.Format(CultureInfo.InvariantCulture, format, arg0, arg1, arg2), null); } + /// + /// Logs a formatted warning message with a custom format provider. + /// + /// The format provider. + /// The format string. + /// The format arguments. public void WarnFormat(IFormatProvider provider, string format, params object[] args) { _logger.Log(null, Level.Warn, string.Format(provider, format, args), null); } + #endregion #region Error Methods + + /// + /// Logs an error message. + /// + /// The message to log. public void Error(object message) { _fileLogger.Error(message); } + /// + /// Logs an error message with an exception. + /// + /// The message to log. + /// The exception to log. public void Error(object message, Exception exception) { _fileLogger.Error(message); } + /// + /// Logs a formatted error message. + /// + /// The format string. + /// The format arguments. public void ErrorFormat(string format, params object[] args) { _logger.Log(null, Level.Error, string.Format(CultureInfo.InvariantCulture, format, args), null); } + /// + /// Logs a formatted error message with one argument. + /// + /// The format string. + /// The first format argument. public void ErrorFormat(string format, object arg0) { _logger.Log(null, Level.Error, string.Format(CultureInfo.InvariantCulture, format, arg0), null); } + /// + /// Logs a formatted error message with two arguments. + /// + /// The format string. + /// The first format argument. + /// The second format argument. public void ErrorFormat(string format, object arg0, object arg1) { _logger.Log(null, Level.Error, string.Format(CultureInfo.InvariantCulture, format, arg0, arg1), null); } + /// + /// Logs a formatted error message with three arguments. + /// + /// The format string. + /// The first format argument. + /// The second format argument. + /// The third format argument. public void ErrorFormat(string format, object arg0, object arg1, object arg2) { _logger.Log(null, Level.Error, string.Format(CultureInfo.InvariantCulture, format, arg0, arg1, arg2), null); } + /// + /// Logs a formatted error message with a custom format provider. + /// + /// The format provider. + /// The format string. + /// The format arguments. public void ErrorFormat(IFormatProvider provider, string format, params object[] args) { _logger.Log(null, Level.Error, string.Format(provider, format, args), null); @@ -183,40 +384,82 @@ public void ErrorFormat(IFormatProvider provider, string format, params object[] #endregion #region Fatal Methods + + /// + /// Logs a fatal message. + /// + /// The message to log. public void Fatal(object message) { _fileLogger.Fatal(message); } + /// + /// Logs a fatal message with an exception. + /// + /// The message to log. + /// The exception to log. public void Fatal(object message, Exception exception) { _fileLogger.Fatal(message); } + /// + /// Logs a formatted fatal message. + /// + /// The format string. + /// The format arguments. public void FatalFormat(string format, params object[] args) { _logger.Log(null, Level.Fatal, string.Format(CultureInfo.InvariantCulture, format, args), null); } + /// + /// Logs a formatted fatal message with one argument. + /// + /// The format string. + /// The first format argument. public void FatalFormat(string format, object arg0) { _logger.Log(null, Level.Fatal, string.Format(CultureInfo.InvariantCulture, format, arg0), null); } + /// + /// Logs a formatted fatal message with two arguments. + /// + /// The format string. + /// The first format argument. + /// The second format argument. public void FatalFormat(string format, object arg0, object arg1) { _logger.Log(null, Level.Fatal, string.Format(CultureInfo.InvariantCulture, format, arg0, arg1), null); } + /// + /// Logs a formatted fatal message with three arguments. + /// + /// The format string. + /// The first format argument. + /// The second format argument. + /// The third format argument. public void FatalFormat(string format, object arg0, object arg1, object arg2) { _logger.Log(null, Level.Fatal, string.Format(CultureInfo.InvariantCulture, format, arg0, arg1, arg2), null); } + /// + /// Logs a formatted fatal message with a custom format provider. + /// + /// The format provider. + /// The format string. + /// The format arguments. public void FatalFormat(IFormatProvider provider, string format, params object[] args) { _logger.Log(null, Level.Fatal, string.Format(provider, format, args), null); } + + #endregion + #endregion } diff --git a/src/LCT.Common/Logging/SpectreLogger.cs b/src/LCT.Common/Logging/SpectreLogger.cs index 8910a4714..cea3eadc3 100644 --- a/src/LCT.Common/Logging/SpectreLogger.cs +++ b/src/LCT.Common/Logging/SpectreLogger.cs @@ -11,24 +11,63 @@ namespace LCT.Common.Logging { + /// + /// Implements a custom logger that integrates Spectre.Console for enhanced console output with log4net. + /// public class SpectreLogger : ILogger { + #region Fields + private readonly string _loggerName; + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + /// The name of the logger. public SpectreLogger(string loggerName) { _loggerName = loggerName; } + #endregion + + #region Properties + + /// + /// Gets the name of the logger. + /// public string Name => _loggerName; + /// + /// Gets the logger repository (not implemented). + /// ILoggerRepository ILogger.Repository => throw new NotImplementedException(); + #endregion + + #region Methods + + /// + /// Determines whether logging is enabled for the specified level. + /// + /// The logging level. + /// True if logging is enabled for the level; otherwise, false. public bool IsEnabledFor(Level level) { return true; } + /// + /// Logs a message with the specified level and exception using both file and console output. + /// + /// The type declaring the caller stack boundary. + /// The logging level. + /// The message to log. + /// The exception to log. public void Log(Type callerStackBoundaryDeclaringType, Level level, object message, Exception exception) { var fileLogger = LogManager.GetLogger(_loggerName); @@ -79,9 +118,16 @@ public void Log(Type callerStackBoundaryDeclaringType, Level level, object messa }); } } + + /// + /// Logs a logging event (not implemented). + /// + /// The logging event. void ILogger.Log(LoggingEvent logEvent) { throw new NotImplementedException(); } + + #endregion } } diff --git a/src/LCT.Common/Model/CatoolInfo.cs b/src/LCT.Common/Model/CatoolInfo.cs index bb8ee5f11..8e7f6af91 100644 --- a/src/LCT.Common/Model/CatoolInfo.cs +++ b/src/LCT.Common/Model/CatoolInfo.cs @@ -7,10 +7,24 @@ namespace LCT.Common.Model { + /// + /// Represents information about the CA tool. + /// [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class CatoolInfo { + #region Properties + + /// + /// Gets or sets the CA tool version. + /// public string CatoolVersion { get; set; } + + /// + /// Gets or sets the CA tool running location. + /// public string CatoolRunningLocation { get; set; } + + #endregion } } \ No newline at end of file diff --git a/src/LCT.Common/Model/ComlianceValidator.cs b/src/LCT.Common/Model/ComlianceValidator.cs index 290ea2b9d..b00083cd8 100644 --- a/src/LCT.Common/Model/ComlianceValidator.cs +++ b/src/LCT.Common/Model/ComlianceValidator.cs @@ -10,36 +10,81 @@ namespace LCT.Common.ComplianceValidator { using System.Text.Json.Serialization; + /// + /// Represents the compliance settings model containing exception components. + /// public class ComplianceSettingsModel { + #region Properties + + /// + /// Gets or sets the list of compliance exception components. + /// [JsonPropertyName("complianceExceptionComponents")] public List ComplianceExceptionComponents { get; set; } + + #endregion } + /// + /// Represents a compliance exception component with instructions. + /// public class ComplianceExceptionComponent { + #region Properties + + /// + /// Gets or sets the component identifier. + /// [JsonPropertyName("id")] public string Id { get; set; } + /// + /// Gets or sets the component name. + /// [JsonPropertyName("name")] public string Name { get; set; } + /// + /// Gets or sets the component description. + /// [JsonPropertyName("description")] public string Description { get; set; } + /// + /// Gets or sets the list of package URLs (PURL). + /// [JsonPropertyName("purl")] public List Purl { get; set; } + /// + /// Gets or sets the compliance instructions. + /// [JsonPropertyName("complianceInstructions")] public ComplianceInstructions ComplianceInstructions { get; set; } + + #endregion } + /// + /// Represents compliance instructions with warnings and recommendations. + /// public class ComplianceInstructions { + #region Properties + + /// + /// Gets or sets the warning message. + /// [JsonPropertyName("warningMessage")] public string WarningMessage { get; set; } + /// + /// Gets or sets the recommendation. + /// [JsonPropertyName("recommendation")] public string Recommendation { get; set; } + + #endregion } } \ No newline at end of file diff --git a/src/LCT.Common/Model/ComparisonBomData.cs b/src/LCT.Common/Model/ComparisonBomData.cs index 25ce618d3..4edc2cc70 100644 --- a/src/LCT.Common/Model/ComparisonBomData.cs +++ b/src/LCT.Common/Model/ComparisonBomData.cs @@ -9,36 +9,138 @@ namespace LCT.Common.Model { /// - /// ComparisonBomData model + /// Represents BOM data used for comparison operations with status tracking. /// [ExcludeFromCodeCoverage] public class ComparisonBomData { + #region Properties + + /// + /// Gets or sets the component name. + /// public string Name { get; set; } + + /// + /// Gets or sets the component group. + /// public string Group { get; set; } + + /// + /// Gets or sets the component version. + /// public string Version { get; set; } + + /// + /// Gets or sets the component external identifier. + /// public string ComponentExternalId { get; set; } + + /// + /// Gets or sets the release external identifier. + /// public string ReleaseExternalId { get; set; } + + /// + /// Gets or sets the package URL. + /// public string PackageUrl { get; set; } + + /// + /// Gets or sets the source URL. + /// public string SourceUrl { get; set; } + + /// + /// Gets or sets the download URL. + /// public string DownloadUrl { get; set; } + + /// + /// Gets or sets the array of patch URLs. + /// public string[] PatchURls { get; set; } + + /// + /// Gets or sets the component status. + /// public string ComponentStatus { get; set; } + + /// + /// Gets or sets the release status. + /// public string ReleaseStatus { get; set; } + + /// + /// Gets or sets the approved status. + /// public string ApprovedStatus { get; set; } + + /// + /// Gets or sets a value indicating whether the component was created. + /// public string IsComponentCreated { get; set; } + + /// + /// Gets or sets a value indicating whether the release was created. + /// public string IsReleaseCreated { get; set; } + + /// + /// Gets or sets the FOSSology upload status. + /// public string FossologyUploadStatus { get; set; } + + /// + /// Gets or sets the release attachment link. + /// public string ReleaseAttachmentLink { get; set; } + + /// + /// Gets or sets the release link. + /// public string ReleaseLink { get; set; } + + /// + /// Gets or sets the FOSSology link. + /// public string FossologyLink { get; set; } + + /// + /// Gets or sets the release identifier. + /// public string ReleaseID { get; set; } + + /// + /// Gets or sets the Alpine source information. + /// public string AlpineSource { get; set; } + + /// + /// Gets or sets the parent release name. + /// public string ParentReleaseName { get; set; } + + /// + /// Gets or sets the FOSSology upload identifier. + /// public string FossologyUploadId { get; set; } + + /// + /// Gets or sets the clearing state. + /// public string ClearingState { get; set; } + + /// + /// Gets or sets the user who created the release. + /// public string ReleaseCreatedBy { get; set; } + + /// + /// Gets or sets a value indicating whether the source attachment status is successful. + /// public bool SourceAttachmentStatus { get; set; } = false; + #endregion } } diff --git a/src/LCT.Common/Model/Components.cs b/src/LCT.Common/Model/Components.cs index 34c9e0a26..1b0ea9a00 100644 --- a/src/LCT.Common/Model/Components.cs +++ b/src/LCT.Common/Model/Components.cs @@ -10,67 +10,139 @@ namespace LCT.Common.Model { /// - /// Component model + /// Represents a software component with its metadata and attributes. /// [ExcludeFromCodeCoverage] public class Components { + #region Properties + + /// + /// Gets or sets the component name. + /// [JsonProperty("name")] public string Name { get; set; } + + /// + /// Gets or sets the component group. + /// [JsonProperty("group")] public string Group { get; set; } + /// + /// Gets or sets the component version. + /// [JsonProperty("version")] public string Version { get; set; } + /// + /// Gets or sets the component external identifier. + /// [JsonProperty("componentExternalId")] public string ComponentExternalId { get; set; } + /// + /// Gets or sets the release external identifier. + /// [JsonProperty("releaseExternalId")] public string ReleaseExternalId { get; set; } + /// + /// Gets or sets the package URL. + /// [JsonProperty("packageUrl")] public string PackageUrl { get; set; } + /// + /// Gets or sets the source URL. + /// [JsonProperty("sourceUrl")] public string SourceUrl { get; set; } + /// + /// Gets or sets the download URL. + /// [JsonProperty("downloadUrl")] public string DownloadUrl { get; set; } + /// + /// Gets or sets the array of patch URLs. + /// [JsonProperty("patchURLs")] public string[] PatchURLs { get; set; } + /// + /// Gets or sets the Alpine source data. + /// [JsonProperty("alpineSourceData")] public string AlpineSourceData { get; set; } + /// + /// Gets or sets the upload identifier. + /// [JsonIgnore] public string UploadId { get; set; } + /// + /// Gets or sets the release link. + /// [JsonIgnore] public string ReleaseLink { get; set; } + /// + /// Gets or sets the release identifier. + /// [JsonIgnore] public string ReleaseId { get; set; } + /// + /// Gets or sets the folder path. + /// [JsonIgnore] public string FolderPath { get; set; } + /// + /// Gets or sets the project type. + /// [JsonIgnore] public string ProjectType { get; set; } + /// + /// Gets or sets a value indicating whether this is a development component. + /// [JsonIgnore] public string IsDev { get; set; } + + /// + /// Gets or sets the exclude component flag. + /// [JsonIgnore] public string ExcludeComponent { get; set; } + + /// + /// Gets or sets the user who created the release. + /// [JsonIgnore] public string ReleaseCreatedBy { get; set; } + + /// + /// Gets or sets a value indicating whether the component is invalid by PURL ID. + /// [JsonIgnore] public bool InvalidComponentByPurlId { get; set; } = false; + + /// + /// Gets or sets the component link. + /// [JsonIgnore] public string ComponentLink { get; set; } + + /// + /// Gets or sets the component identifier. + /// [JsonIgnore] public string ComponentId { get; set; } + #endregion } } diff --git a/src/LCT.Common/Model/ComponentsRequireAction.cs b/src/LCT.Common/Model/ComponentsRequireAction.cs index 9edfbb20b..42c390a9c 100644 --- a/src/LCT.Common/Model/ComponentsRequireAction.cs +++ b/src/LCT.Common/Model/ComponentsRequireAction.cs @@ -9,13 +9,29 @@ namespace LCT.Common.Model { + /// + /// Represents components that require action based on various conditions. + /// [ExcludeFromCodeCoverage] public class ComponentsRequireAction { + #region Properties + + /// + /// Gets or sets the list of components without source attachment. + /// public List ListofComponentsWithoutSourceAttachment { get; set; } = new List(); + /// + /// Gets or sets the list of components without source download URL. + /// public List ListofComponentsWithoutSrcDownloadUrl { get; set; } = new List(); + /// + /// Gets or sets the list of components not uploaded. + /// public List ListofComponentsNotUploaded { get; set; } = new List(); + + #endregion } } diff --git a/src/LCT.Common/Model/Config.cs b/src/LCT.Common/Model/Config.cs index f198724ba..4f723623a 100644 --- a/src/LCT.Common/Model/Config.cs +++ b/src/LCT.Common/Model/Config.cs @@ -11,28 +11,88 @@ namespace LCT.Common.Model { /// - /// Config + /// Represents the configuration settings for the application. /// [ExcludeFromCodeCoverage] public class Config { + #region Properties + + /// + /// Gets or sets the array of include patterns. + /// public string[] Include { get; set; } + + /// + /// Gets or sets the array of exclude patterns. + /// public string[] Exclude { get; set; } + + /// + /// Gets or sets the Artifactory configuration. + /// public Artifactory Artifactory { get; set; } + + /// + /// Gets or sets the release repository. + /// public string ReleaseRepo { get; set; } + + /// + /// Gets or sets the development dependency repository. + /// public string DevDepRepo { get; set; } + #endregion } + + /// + /// Represents Artifactory repository configuration. + /// public class Artifactory { + #region Properties + + /// + /// Gets or sets the list of third-party repositories. + /// public List ThirdPartyRepos { get; set; } + + /// + /// Gets or sets the array of internal repositories. + /// public string[] InternalRepos { get; set; } = Array.Empty(); + + /// + /// Gets or sets the array of development repositories. + /// public string[] DevRepos { get; set; } + + /// + /// Gets or sets the array of remote repositories. + /// public string[] RemoteRepos { get; set; } + + #endregion } + + /// + /// Represents a third-party repository configuration. + /// public class ThirdPartyRepo { + #region Properties + + /// + /// Gets or sets the repository name. + /// public string Name { get; set; } + + /// + /// Gets or sets a value indicating whether upload is enabled. + /// public bool Upload { get; set; } + + #endregion } } diff --git a/src/LCT.Common/Model/KpiNames.cs b/src/LCT.Common/Model/KpiNames.cs index 9e704a6dd..806b4a607 100644 --- a/src/LCT.Common/Model/KpiNames.cs +++ b/src/LCT.Common/Model/KpiNames.cs @@ -10,81 +10,199 @@ namespace LCT.Common.Model { + /// + /// Represents the names of various KPI metrics used for tracking components and packages. + /// [ExcludeFromCodeCoverage] public class KpiNames { + #region Properties + /// + /// Gets or sets the count of components in the input file. + /// public string ComponentsInInputFile { get; set; } + /// + /// Gets or sets the count of development components. + /// public string DevelopmentComponents { get; set; } + /// + /// Gets or sets the count of bundled components. + /// public string BundledComponents { get; set; } + /// + /// Gets or sets the count of duplicate components. + /// public string DuplicateComponents { get; set; } + /// + /// Gets or sets the count of internal components. + /// public string InternalComponents { get; set; } + /// + /// Gets or sets the count of packages present in the 3rd party repository. + /// public string PackagesPresentIn3rdPartyRepo { get; set; } + /// + /// Gets or sets the count of packages present in the development dependency repository. + /// public string PackagesPresentInDevDepRepo { get; set; } + /// + /// Gets or sets the count of packages present in the release repository. + /// public string PackagesPresentInReleaseRepo { get; set; } + /// + /// Gets or sets the count of packages not present in the official repository. + /// public string PackagesNotPresentInOfficialRepo { get; set; } + /// + /// Gets or sets the count of invalid components excluded. + /// public string InvalidComponentsExcluded { get; set; } + /// + /// Gets or sets the count of components manually excluded from SW360. + /// public string ManuallyExcludedSw360 { get; set; } + /// + /// Gets or sets the count of components with source URL. + /// public string ComponentsWithSourceURL { get; set; } + /// + /// Gets or sets the count of components in the BOM. + /// public string ComponentsInBOM { get; set; } + /// + /// Gets or sets the count of components added from the SBOM template. + /// public string ComponentsAddedFromSBOMTemplate { get; set; } + /// + /// Gets or sets the count of components overwritten from the SBOM template. + /// public string ComponentsOverWrittenFromSBOMTemplate { get; set; } + /// + /// Gets or sets the count of components from the SPDX imported as baseline entries. + /// public string ComponentsFromTheSPDXImportedAsBaselineEntries { get; set; } + + /// + /// Gets or sets the count of components from the BOM. + /// public string ComponentsFromBOM { get; set; } + /// + /// Gets or sets the count of releases created in SW360. + /// public string ReleasesCreatedInSW360 { get; set; } + /// + /// Gets or sets the count of releases that exist in SW360. + /// public string ReleasesExistsInSW360 { get; set; } + /// + /// Gets or sets the count of releases without source download URL. + /// public string ReleasesWithoutSourceDownloadURL { get; set; } + /// + /// Gets or sets the count of releases with source download URL. + /// public string ReleasesWithSourceDownloadURL { get; set; } + /// + /// Gets or sets the count of releases not created in SW360. + /// public string ReleasesNotCreatedInSW360 { get; set; } + /// + /// Gets or sets the count of components without source and package URL. + /// public string ComponentsWithoutSourceAndPackageURL { get; set; } + /// + /// Gets or sets the count of components without package URL. + /// public string ComponentsWithoutPackageURL { get; set; } + /// + /// Gets or sets the count of components uploaded in FOSSology. + /// public string ComponentsUploadedInFOSSology { get; set; } + /// + /// Gets or sets the count of components not uploaded in FOSSology. + /// public string ComponentsNotUploadedInFOSSology { get; set; } + /// + /// Gets or sets the total count of duplicate and invalid components. + /// public string TotalDuplicateAndInValidComponents { get; set; } + + /// + /// Gets or sets the count of packages in not approved state. + /// public string PackagesInNotApprovedState { get; set; } + /// + /// Gets or sets the count of packages in approved state. + /// public string PackagesInApprovedState { get; set; } + /// + /// Gets or sets the count of packages copied to the Siparty repository. + /// public string PackagesCopiedToSipartyRepo { get; set; } + /// + /// Gets or sets the count of packages not copied to the Siparty repository. + /// public string PackagesNotCopiedToSipartyRepo { get; set; } + /// + /// Gets or sets the count of packages not existing in the repository. + /// public string PackagesNotExistingInRepository { get; set; } + /// + /// Gets or sets the count of packages not actioned due to error. + /// public string PackagesNotActionedDueToError { get; set; } + /// + /// Gets or sets the count of packages copied to the Siparty development dependency repository. + /// public string PackagesCopiedToSipartyDevDepRepo { get; set; } + /// + /// Gets or sets the count of packages not copied to the Siparty development dependency repository. + /// public string PackagesNotCopiedToSipartyDevDepRepo { get; set; } + /// + /// Gets or sets the count of packages moved to the repository. + /// public string PackagesMovedToRepo { get; set; } + /// + /// Gets or sets the count of packages not moved to the repository. + /// public string PackagesNotMovedToRepo { get; set; } + #endregion } } diff --git a/src/LCT.Common/Model/ListofPerametersForCli.cs b/src/LCT.Common/Model/ListofPerametersForCli.cs index 8404649e7..a782c4ded 100644 --- a/src/LCT.Common/Model/ListofPerametersForCli.cs +++ b/src/LCT.Common/Model/ListofPerametersForCli.cs @@ -8,12 +8,34 @@ namespace LCT.Common.Model { + /// + /// Represents a list of parameters for the CLI. + /// [ExcludeFromCodeCoverage] public class ListofPerametersForCli { + #region Properties + + /// + /// Gets or sets the internal repository list. + /// public string InternalRepoList { get; set; } + + /// + /// Gets or sets the include pattern. + /// public string Include { get; set; } + + /// + /// Gets or sets the exclude pattern. + /// public string Exclude { get; set; } + + /// + /// Gets or sets the components to exclude. + /// public string ExcludeComponents { get; set; } + + #endregion } } diff --git a/src/LCT.Common/Model/MultipleVersionValues.cs b/src/LCT.Common/Model/MultipleVersionValues.cs index c3a02922b..1f1021675 100644 --- a/src/LCT.Common/Model/MultipleVersionValues.cs +++ b/src/LCT.Common/Model/MultipleVersionValues.cs @@ -15,16 +15,48 @@ namespace LCT.Common.Model [ExcludeFromCodeCoverage] public class MultipleVersionValues { + #region Properties + + /// + /// Gets or sets the component name. + /// public string ComponentName { get; set; } + + /// + /// Gets or sets the component version. + /// public string ComponentVersion { get; set; } + + /// + /// Gets or sets the package where the component was found. + /// public string PackageFoundIn { get; set; } + #endregion } + /// + /// Represents multiple versions found across different package managers. + /// public class MultipleVersions { + #region Properties + + /// + /// Gets or sets the list of NPM packages with multiple versions. + /// public List Npm { get; set; } + + /// + /// Gets or sets the list of NuGet packages with multiple versions. + /// public List Nuget { get; set; } + + /// + /// Gets or sets the list of Conan packages with multiple versions. + /// public List Conan { get; set; } + + #endregion } } diff --git a/src/LCT.Common/Model/SW360ConnectionSettings.cs b/src/LCT.Common/Model/SW360ConnectionSettings.cs index 9f16f18c3..77947f5cd 100644 --- a/src/LCT.Common/Model/SW360ConnectionSettings.cs +++ b/src/LCT.Common/Model/SW360ConnectionSettings.cs @@ -6,14 +6,40 @@ namespace LCT.Common.Model { + /// + /// Represents connection settings for SW360 integration. + /// [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class SW360ConnectionSettings { + #region Properties + + /// + /// Gets or sets the SW360 server URL. + /// public string SW360URL { get; set; } + + /// + /// Gets or sets the SW360 authentication token type. + /// public string SW360AuthTokenType { get; set; } + + /// + /// Gets or sets the SW360 authentication token. + /// public string Sw360Token { get; set; } + + /// + /// Gets or sets a value indicating whether test mode is enabled. + /// public bool IsTestMode { get; set; } + + /// + /// Gets or sets the connection timeout in milliseconds. + /// public int Timeout { get; set; } + #endregion } } + \ No newline at end of file diff --git a/src/LCT.Common/Model/SpdxBomData.cs b/src/LCT.Common/Model/SpdxBomData.cs index 736120e9c..4f054bd26 100644 --- a/src/LCT.Common/Model/SpdxBomData.cs +++ b/src/LCT.Common/Model/SpdxBomData.cs @@ -11,139 +11,311 @@ namespace LCT.Common.Model { + /// + /// Represents the root SPDX BOM data structure. + /// [ExcludeFromCodeCoverage] public class SpdxBomData { + #region Properties + + /// + /// Gets or sets the SPDX version. + /// [JsonProperty("spdxVersion")] public string SpdxVersion { get; set; } + /// + /// Gets or sets the data license. + /// [JsonProperty("dataLicense")] public string DataLicense { get; set; } + /// + /// Gets or sets the SPDX identifier. + /// public string SPDXID { get; set; } + /// + /// Gets or sets the document name. + /// [JsonProperty("name")] public string Name { get; set; } + /// + /// Gets or sets the document namespace. + /// [JsonProperty("documentNamespace")] public string DocumentNamespace { get; set; } + /// + /// Gets or sets the creation information. + /// [JsonProperty("creationInfo")] public CreationInfo CreationInfo { get; set; } + /// + /// Gets or sets the list of packages. + /// [JsonProperty("packages")] public List Packages { get; set; } + /// + /// Gets or sets the list of files. + /// [JsonProperty("files")] public List Files { get; set; } + /// + /// Gets or sets the list of relationships. + /// [JsonProperty("relationships")] public List Relationships { get; set; } + + #endregion } + + /// + /// Represents a checksum for verifying file integrity. + /// [ExcludeFromCodeCoverage] public class Checksum { + #region Properties + + /// + /// Gets or sets the checksum algorithm. + /// [JsonProperty("algorithm")] public string Algorithm { get; set; } + /// + /// Gets or sets the checksum value. + /// [JsonProperty("checksumValue")] public string ChecksumValue { get; set; } + + #endregion } + + /// + /// Represents creation information for the SPDX document. + /// [ExcludeFromCodeCoverage] public class CreationInfo { + #region Properties + + /// + /// Gets or sets the license list version. + /// [JsonProperty("licenseListVersion")] public string LicenseListVersion { get; set; } + /// + /// Gets or sets the list of creators. + /// [JsonProperty("creators")] public List Creators { get; set; } + /// + /// Gets or sets the creation date and time. + /// [JsonProperty("created")] public DateTime Created { get; set; } + + #endregion } + + /// + /// Represents an external reference for a package. + /// [ExcludeFromCodeCoverage] public class ExternalRef { + #region Properties + + /// + /// Gets or sets the reference category. + /// [JsonProperty("referenceCategory")] public string ReferenceCategory { get; set; } + /// + /// Gets or sets the reference type. + /// [JsonProperty("referenceType")] public string ReferenceType { get; set; } + /// + /// Gets or sets the reference locator. + /// [JsonProperty("referenceLocator")] public string ReferenceLocator { get; set; } + + #endregion } + + /// + /// Represents a file in the SPDX document. + /// [ExcludeFromCodeCoverage] public class File { + #region Properties + + /// + /// Gets or sets the file name. + /// [JsonProperty("fileName")] public string FileName { get; set; } + /// + /// Gets or sets the SPDX identifier for the file. + /// public string SPDXID { get; set; } + /// + /// Gets or sets the list of file types. + /// [JsonProperty("fileTypes")] public List FileTypes { get; set; } + /// + /// Gets or sets the list of checksums for the file. + /// [JsonProperty("checksums")] public List Checksums { get; set; } + /// + /// Gets or sets the concluded license. + /// [JsonProperty("licenseConcluded")] public string LicenseConcluded { get; set; } + /// + /// Gets or sets the license information found in the file. + /// [JsonProperty("licenseInfoInFiles")] public List LicenseInfoInFiles { get; set; } + /// + /// Gets or sets the copyright text. + /// [JsonProperty("copyrightText")] public string CopyrightText { get; set; } + + #endregion } + + /// + /// Represents a package in the SPDX document. + /// [ExcludeFromCodeCoverage] public class Package { + #region Properties + + /// + /// Gets or sets the package name. + /// [JsonProperty("name")] public string Name { get; set; } + /// + /// Gets or sets the SPDX identifier for the package. + /// public string SPDXID { get; set; } + /// + /// Gets or sets the version information. + /// [JsonProperty("versionInfo")] public string VersionInfo { get; set; } + /// + /// Gets or sets the supplier information. + /// [JsonProperty("supplier")] public string Supplier { get; set; } + /// + /// Gets or sets the download location. + /// [JsonProperty("downloadLocation")] public string DownloadLocation { get; set; } + /// + /// Gets or sets a value indicating whether files were analyzed. + /// [JsonProperty("filesAnalyzed")] public bool FilesAnalyzed { get; set; } + /// + /// Gets or sets the list of checksums for the package. + /// [JsonProperty("checksums")] public List Checksums { get; set; } + /// + /// Gets or sets the source information. + /// [JsonProperty("sourceInfo")] public string SourceInfo { get; set; } + /// + /// Gets or sets the concluded license. + /// [JsonProperty("licenseConcluded")] public string LicenseConcluded { get; set; } + /// + /// Gets or sets the declared license. + /// [JsonProperty("licenseDeclared")] public string LicenseDeclared { get; set; } + /// + /// Gets or sets the copyright text. + /// [JsonProperty("copyrightText")] public string CopyrightText { get; set; } + /// + /// Gets or sets the list of external references. + /// [JsonProperty("externalRefs")] public List ExternalRefs { get; set; } + + #endregion } + + /// + /// Represents a relationship between SPDX elements. + /// [ExcludeFromCodeCoverage] public class Relationship { + #region Properties + + /// + /// Gets or sets the SPDX element identifier. + /// [JsonProperty("spdxElementId")] public string SpdxElementId { get; set; } + /// + /// Gets or sets the related SPDX element identifier. + /// [JsonProperty("relatedSpdxElement")] public string RelatedSpdxElement { get; set; } + /// + /// Gets or sets the relationship type. + /// [JsonProperty("relationshipType")] public string RelationshipType { get; set; } + + #endregion } } diff --git a/src/LCT.Common/PipelineArtifactUploader.cs b/src/LCT.Common/PipelineArtifactUploader.cs index 6994e5b13..7cb89ad1e 100644 --- a/src/LCT.Common/PipelineArtifactUploader.cs +++ b/src/LCT.Common/PipelineArtifactUploader.cs @@ -14,12 +14,21 @@ namespace LCT.Common { public static class PipelineArtifactUploader { + #region Fields + static readonly ILog Logger = LoggerFactory.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); public const string LogArtifactFolderName = "ContinuousClearing_Log"; public const string BomArtifactFolderName = "ContinuousClearing_Bom"; public const string LogContainerFolderName = "Container_Log"; public const string BomContainerFolderName = "Container_Bom"; + #endregion + + #region Methods + + /// + /// Uploads both logs and BOM artifacts to the pipeline. + /// public static void UploadArtifacts() { UploadBom(); @@ -91,5 +100,7 @@ public static void PrintWarning(string content) Console.WriteLine($"##[warning]{content}"); } } + + #endregion } } diff --git a/src/LCT.Common/ProcessAsyncHelper.cs b/src/LCT.Common/ProcessAsyncHelper.cs index fbf106897..c53a1f6ce 100644 --- a/src/LCT.Common/ProcessAsyncHelper.cs +++ b/src/LCT.Common/ProcessAsyncHelper.cs @@ -19,7 +19,14 @@ namespace LCT.Common /// public static class ProcessAsyncHelper { + #region Fields + static readonly ILog Logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + #endregion + + #region Methods + /// /// Run a process asynchronously /// To capture STDOUT, set StartInfo.RedirectStandardOutput to TRUE @@ -94,6 +101,11 @@ public static async Task RunAsync(ProcessStartInfo startInfo, int? timeo return result; } + + /// + /// Reads the output stream from the process asynchronously. + /// + /// The process to read output from. public static void ReadOutputStreamProcess(Process process) { if (process.StartInfo.RedirectStandardOutput) @@ -105,6 +117,13 @@ public static void ReadOutputStreamProcess(Process process) process.BeginErrorReadLine(); } } + + /// + /// Handles standard output stream from the process. + /// + /// The process to handle output from. + /// The list of tasks to track completion. + /// A StringBuilder containing the standard output. public static StringBuilder STDOutHandler(Process process, List processTasks) { var stdOutBuilder = new StringBuilder(); @@ -129,6 +148,13 @@ public static StringBuilder STDOutHandler(Process process, List processTas return stdOutBuilder; } + + /// + /// Handles standard error stream from the process. + /// + /// The process to handle error output from. + /// The list of tasks to track completion. + /// A StringBuilder containing the standard error output. public static StringBuilder STDErrorHandler(Process process, List processTasks) { var stdErrBuilder = new StringBuilder(); @@ -154,6 +180,7 @@ public static StringBuilder STDErrorHandler(Process process, List processT } + #endregion } } diff --git a/src/LCT.Common/Result.cs b/src/LCT.Common/Result.cs index 1946258e5..ca36a6770 100644 --- a/src/LCT.Common/Result.cs +++ b/src/LCT.Common/Result.cs @@ -14,6 +14,8 @@ namespace LCT.Common [ExcludeFromCodeCoverage] public class Result { + #region Properties + /// /// Exit code /// If NULL, process exited due to timeout @@ -29,5 +31,7 @@ public class Result /// Standard output stream /// public string StdOut { get; set; } = ""; + + #endregion } } diff --git a/src/LCT.Common/Runtime/EnvironmentType.cs b/src/LCT.Common/Runtime/EnvironmentType.cs index dd5326a84..78350cb20 100644 --- a/src/LCT.Common/Runtime/EnvironmentType.cs +++ b/src/LCT.Common/Runtime/EnvironmentType.cs @@ -7,13 +7,28 @@ namespace LCT.Common.Runtime { /// - /// The EnvironmentType enum + /// Represents the type of runtime environment where the application is executing. /// public enum EnvironmentType { + /// + /// Unknown or unrecognized environment. + /// Unknown = 0, + + /// + /// GitLab CI/CD environment. + /// GitLab = 1, + + /// + /// Azure DevOps build pipeline environment. + /// AzurePipeline = 2, + + /// + /// Azure DevOps release pipeline environment. + /// AzureRelease = 3 } } diff --git a/src/LCT.Common/Runtime/RuntimeEnvironment.cs b/src/LCT.Common/Runtime/RuntimeEnvironment.cs index fe7af2636..6b699b7ac 100644 --- a/src/LCT.Common/Runtime/RuntimeEnvironment.cs +++ b/src/LCT.Common/Runtime/RuntimeEnvironment.cs @@ -7,10 +7,16 @@ namespace LCT.Common.Runtime { /// - /// The RuntimeEnvironment class + /// Provides utilities for detecting the runtime environment (Azure, GitLab, etc.). /// public static class RuntimeEnvironment { + #region Methods + + /// + /// Gets the current runtime environment type based on environment variables. + /// + /// The detected environment type (AzureRelease, AzurePipeline, GitLab, or Unknown). public static EnvironmentType GetEnvironment() { // Azure Release Pipeline contains both "Release_ReleaseId" and @@ -36,6 +42,11 @@ public static EnvironmentType GetEnvironment() return EnvironmentType.Unknown; } + /// + /// Checks if an environment variable is defined and has a non-null, non-whitespace value. + /// + /// The name of the environment variable to check. + /// True if the environment variable is defined and has a value; otherwise, false. public static bool IsEnvironmentVariableDefined(string name) { string value = System.Environment.GetEnvironmentVariable(name); @@ -45,5 +56,7 @@ public static bool IsEnvironmentVariableDefined(string name) } return true; } + + #endregion } } diff --git a/src/LCT.Common/SettingsManager.cs b/src/LCT.Common/SettingsManager.cs index 75851d864..caa9dc43a 100644 --- a/src/LCT.Common/SettingsManager.cs +++ b/src/LCT.Common/SettingsManager.cs @@ -20,10 +20,21 @@ namespace LCT.Common /// public class SettingsManager : ISettingsManager { - public string BasePath { get; private set; } = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + #region Fields + static readonly ILog Logger = LoggerFactory.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly EnvironmentHelper environmentHelper = new EnvironmentHelper(); + #endregion + + #region Properties + + public string BasePath { get; private set; } = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + + #endregion + + #region Methods + /// /// Reads the Configuration from input args and json setting file /// @@ -86,6 +97,9 @@ public T ReadConfiguration(string[] args, string jsonSettingsFileName, IEnvir return appSettings; } + /// + /// Displays the CLI usage help from the help text file. + /// public static void DisplayHelp() { @@ -97,6 +111,12 @@ public static void DisplayHelp() sr.Dispose(); } + /// + /// Gets the configuration file path from command line arguments. + /// + /// The command line arguments. + /// The default JSON settings file name. + /// The configuration file path. internal string GetConfigFilePathFromArgs(string[] args, string jsonSettingsFileName) { IConfigurationBuilder settingsFileConfigBuilder = new ConfigurationBuilder() @@ -124,6 +144,11 @@ internal string GetConfigFilePathFromArgs(string[] args, string jsonSettingsFile return settingsFilePath; } + /// + /// Checks required arguments to run based on the current executable type. + /// + /// The application settings. + /// The current executable type (Identifier, Creator, or other). public void CheckRequiredArgsToRun(CommonAppSettings appSettings, string currentExe) { @@ -187,6 +212,11 @@ public void CheckRequiredArgsToRun(CommonAppSettings appSettings, string current Logger.Debug("CheckRequiredArgsToRun():Validating mandatory parameters has completed\n"); } + /// + /// Checks for missing required parameters in the application settings. + /// + /// The application settings. + /// The list of required parameter keys. private static void CheckForMissingParameter(CommonAppSettings appSettings, List reqParameters) { StringBuilder missingParameters = new StringBuilder(); @@ -209,6 +239,12 @@ private static void CheckForMissingParameter(CommonAppSettings appSettings, List } } + /// + /// Gets the nested property value from an object using dot notation. + /// + /// The object to retrieve the property value from. + /// The property key in dot notation (e.g., "Property.SubProperty"). + /// The property value, or null if not found. private static object GetNestedPropertyValue(object obj, string key) { string[] parts = key.Split('.'); @@ -228,6 +264,11 @@ private static object GetNestedPropertyValue(object obj, string key) return currentObject; } + /// + /// Checks if a value is missing, null, empty, or whitespace. + /// + /// The value to check. + /// True if the value is missing; otherwise, false. private static bool IsMissingValue(object value) { if (value is Array array) @@ -242,6 +283,11 @@ private static bool IsMissingValue(object value) return string.IsNullOrWhiteSpace(value?.ToString()); } + + /// + /// Checks if Azure DevOps debug mode is enabled. + /// + /// True if Azure DevOps debug mode is enabled; otherwise, false. public static bool IsAzureDevOpsDebugEnabled() { string azureDevOpsDebug = Environment.GetEnvironmentVariable("System.Debug") ?? string.Empty; @@ -252,10 +298,18 @@ public static bool IsAzureDevOpsDebugEnabled() return false; } + #endregion } + /// + /// Represents settings file configuration. + /// public class SettingsFile { + #region Properties + public string SettingsFilePath { get; set; } + + #endregion } } diff --git a/src/LCT.Common/SpdxBomParser.cs b/src/LCT.Common/SpdxBomParser.cs index b2dd1551a..179be0c45 100644 --- a/src/LCT.Common/SpdxBomParser.cs +++ b/src/LCT.Common/SpdxBomParser.cs @@ -19,9 +19,27 @@ namespace LCT.Common { + /// + /// Parses SPDX BOM files and converts them to CycloneDX format. + /// public class SpdxBomParser : ISpdxBomParser { + #region Fields + + /// + /// The logger instance for logging messages and errors. + /// static readonly ILog Logger = LoggerFactory.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + #endregion Fields + + #region Methods + + /// + /// Parses an SPDX BOM file and converts it to CycloneDX BOM format. + /// + /// The path to the SPDX BOM file to parse. + /// A CycloneDX BOM object containing parsed components and dependencies. public Bom ParseSPDXBom(string filePath) { Logger.DebugFormat("ParseSPDXBom():Starting SPDX BOM parsing for file: {0}", filePath); @@ -68,6 +86,12 @@ public Bom ParseSPDXBom(string filePath) Logger.Debug($"SPDX BOM parsing completed. Final BOM contains {bom.Components?.Count ?? 0} components and {bom.Dependencies?.Count ?? 0} dependencies"); return bom; } + + /// + /// Validates the SPDX version to ensure it matches the expected version. + /// + /// The SPDX BOM data to validate. + /// True if the SPDX version is valid; otherwise, false. private static bool IsValidSpdxVersion(SpdxBomData spdxData) { if (spdxData == null) @@ -92,6 +116,12 @@ private static bool IsValidSpdxVersion(SpdxBomData spdxData) } return isValid; } + + /// + /// Converts SPDX data to BOM format including components and dependencies. + /// + /// The SPDX BOM data to convert. + /// The BOM object to populate. private static void ConvertSpdxDataToBom(SpdxBomData spdxData, ref Bom bom) { Logger.Debug("Starting SPDX data to BOM conversion..."); @@ -108,6 +138,13 @@ private static void ConvertSpdxDataToBom(SpdxBomData spdxData, ref Bom bom) bom.Dependencies = dependencies; Logger.DebugFormat("SBOM conversion completed. Components: {0}, Dependencies: {1}", components.Count, dependencies.Count); } + + /// + /// Adds development property to components based on SPDX relationships. + /// + /// The list of components to update. + /// The SPDX relationships to analyze. + /// The component index for lookups. private static void AddDevelopmentPropertyToComponents(List components, IEnumerable relationships, Dictionary componentIndex) { var devDependencyBomRefs = relationships @@ -129,11 +166,21 @@ private static void AddDevelopmentPropertyToComponents(List component SpdxSbomHelper.AddDevelopmentProperty(component, isDevDependency); } } + + /// + /// Cleans up manufacturer data by setting it to null for all components. + /// + /// The list of components to clean up. private static void CleanupComponentManufacturerData(List components) { components.ForEach(component => component.Manufacturer = null); } + /// + /// Processes SPDX packages and converts them to components with an index. + /// + /// The SPDX packages to process. + /// A tuple containing the list of components and a component index. private static (List components, Dictionary componentIndex) ProcessSpdxPackages(IEnumerable packages) { Logger.Debug("ProcessSpdxPackages():Starting SPDX package processing..."); @@ -154,6 +201,11 @@ private static (List components, Dictionary compon return (components, componentIndex); } + /// + /// Creates a CycloneDX component from an SPDX package. + /// + /// The SPDX package to convert. + /// A Component object if successful; otherwise, null. private static Component CreateComponentFromPackage(Package package) { @@ -189,6 +241,11 @@ private static Component CreateComponentFromPackage(Package package) return component; } + /// + /// Gets the PURL reference from external references. + /// + /// The external references to search. + /// The external reference containing the PURL; otherwise, null. private static ExternalRef GetPurlReference(IEnumerable externalRefs) { return externalRefs.FirstOrDefault(er => @@ -196,6 +253,12 @@ private static ExternalRef GetPurlReference(IEnumerable externalRef er.ReferenceType?.Equals("purl", StringComparison.OrdinalIgnoreCase) == true); } + /// + /// Processes SPDX relationships and converts them to CycloneDX dependencies. + /// + /// The SPDX relationships to process. + /// The component index for lookups. + /// A list of CycloneDX dependencies. private static List ProcessSpdxRelationships(IEnumerable relationships, Dictionary componentIndex) { Logger.Debug("ProcessSpdxRelationships(): Starting SPDX relationships processing..."); @@ -214,6 +277,10 @@ private static List ProcessSpdxRelationships(IEnumerable + /// Gets the set of supported SPDX relationship types. + /// + /// A HashSet containing supported relationship type names. private static HashSet GetSupportedRelationshipTypes() { return new HashSet(StringComparer.OrdinalIgnoreCase) @@ -225,6 +292,13 @@ private static HashSet GetSupportedRelationshipTypes() }; } + /// + /// Builds a dependency map from SPDX relationships. + /// + /// The SPDX relationships to process. + /// The component index for lookups. + /// The set of supported relationship types. + /// A dictionary mapping component references to their dependencies. private static Dictionary> BuildDependencyMap( IEnumerable relationships, Dictionary componentIndex, @@ -247,6 +321,13 @@ private static HashSet GetSupportedRelationshipTypes() return dependencyMap; } + /// + /// Validates whether a relationship is valid and supported. + /// + /// The relationship to validate. + /// The set of supported relationship types. + /// The component index for lookups. + /// True if the relationship is valid; otherwise, false. private static bool IsValidRelationship(Relationship relationship, HashSet supportedTypes, Dictionary componentIndex) { return supportedTypes.Contains(relationship.RelationshipType) && @@ -254,6 +335,12 @@ private static bool IsValidRelationship(Relationship relationship, HashSet + /// Gets the dependency references from a relationship. + /// + /// The relationship to extract references from. + /// The component index for lookups. + /// A tuple containing the dependent reference and dependency reference. private static (string dependentRef, string dependencyRef) GetDependencyRefs(Relationship relationship, Dictionary componentIndex) { Logger.DebugFormat("GetDependencyRefs(): Resolving dependency references for relationship: {0} -> {1}", relationship.SpdxElementId, relationship.RelatedSpdxElement); @@ -269,6 +356,13 @@ private static (string dependentRef, string dependencyRef) GetDependencyRefs(Rel return (dependentRef: childBomRef, dependencyRef: parentBomRef); } + /// + /// Adds a dependency entry to the dependency map. + /// + /// The dependency map to update. + /// The dependent component reference. + /// The dependency component reference. + /// The type of relationship. private static void AddToDependencyMap( Dictionary> dependencyMap, string dependentRef, @@ -288,6 +382,11 @@ private static void AddToDependencyMap( } } + /// + /// Converts the dependency map to CycloneDX dependency format. + /// + /// The dependency map to convert. + /// A list of CycloneDX dependencies. private static List ConvertDependencyMapToCycloneDx(Dictionary> dependencyMap) { return [.. dependencyMap.Select(kvp => new Dependency @@ -297,5 +396,6 @@ private static List ConvertDependencyMapToCycloneDx(Dictionary + /// Provides helper methods for working with SPDX SBOM files. + /// public static class SpdxSbomHelper { + #region Fields + + /// + /// The logger instance for logging messages and errors. + /// static readonly ILog Logger = LoggerFactory.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + #endregion Fields + + #region Methods + + /// + /// Checks and separates valid components from unsupported components in an SPDX file based on project type. + /// + /// The BOM to validate. + /// The project type to validate against. + /// The BOM to populate with unsupported components. public static void CheckValidComponentsFromSpdxfile(Bom bom, string projectType, ref Bom listOfUnsupportedComponents) { Logger.Debug("CheckValidComponentsFromSpdxfile():Start identifying Supported and unsupported packages from spdx input files"); @@ -52,6 +71,12 @@ public static void CheckValidComponentsFromSpdxfile(Bom bom, string projectType, Logger.DebugFormat("CheckValidComponentsFromSpdxfile():Total identified unsupported Dependencies:{0}", listUnsupportedDependencies.Count); Logger.Debug("CheckValidComponentsFromSpdxfile():Completed the Supported and unsupported packages from spdx input files"); } + + /// + /// Adds SPDX properties for unsupported components. + /// + /// The list of unsupported components. + /// The file path of the SPDX file. public static void AddSpdxPropertysForUnsupportedComponents(List UnsupportedComponentList, string filePath) { string filename = Path.GetFileName(filePath); @@ -62,6 +87,12 @@ public static void AddSpdxPropertysForUnsupportedComponents(List Unsu } } + + /// + /// Adds SPDX SBOM file name property to all components in the BOM. + /// + /// The BOM to update. + /// The file path of the SPDX file. public static void AddSpdxSBomFileNameProperty(ref Bom bom, string filePath) { if (bom?.Components != null) @@ -77,17 +108,36 @@ public static void AddSpdxSBomFileNameProperty(ref Bom bom, string filePath) } } + + /// + /// Adds SPDX component properties including file name and identifier type. + /// + /// The SPDX file name. + /// The component to update. public static void AddSpdxComponentProperties(string fileName, Component component) { component.Properties ??= new List(); UpdateOrAddProperty(component.Properties, Dataconstant.Cdx_SpdxFileName, fileName); UpdateOrAddProperty(component.Properties, Dataconstant.Cdx_IdentifierType, Dataconstant.SpdxImport); } + + /// + /// Adds or updates the development property for SPDX components. + /// + /// The development value to set. + /// The component to update. public static void AddDevelopmentPropertyForSpdx(bool devValue, Component component) { component.Properties ??= new List(); UpdateOrAddProperty(component.Properties, Dataconstant.Cdx_IsDevelopment, devValue.ToString()); } + + /// + /// Updates an existing property or adds a new property to the properties list. + /// + /// The properties list to update. + /// The name of the property. + /// The value of the property. private static void UpdateOrAddProperty(List properties, string propertyName, string propertyValue) { var existingProperty = properties.FirstOrDefault(p => p.Name == propertyName); @@ -100,6 +150,12 @@ private static void UpdateOrAddProperty(List properties, string proper properties.Add(new Property { Name = propertyName, Value = propertyValue }); } } + + /// + /// Adds the development property to a component. + /// + /// The component to update. + /// Whether the component is a development dependency. public static void AddDevelopmentProperty(Component component, bool isDevDependency) { component.Properties ??= new List(); @@ -111,5 +167,7 @@ public static void AddDevelopmentProperty(Component component, bool isDevDepende Value = isDevDependency ? "true" : "false" }); } + + #endregion Methods } } diff --git a/src/LCT.Common/TelemetryHelper.cs b/src/LCT.Common/TelemetryHelper.cs index 27cc18a77..dfe12a051 100644 --- a/src/LCT.Common/TelemetryHelper.cs +++ b/src/LCT.Common/TelemetryHelper.cs @@ -19,11 +19,21 @@ namespace LCT.Common { public class TelemetryHelper { + #region Fields + private readonly ILog Logger; private readonly LCT.Telemetry.Telemetry telemetry_; private readonly EnvironmentHelper environmentHelper = new EnvironmentHelper(); private readonly CommonAppSettings appSettings_; + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the TelemetryHelper class. + /// + /// The common application settings. public TelemetryHelper(CommonAppSettings appSettings) { Logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -35,6 +45,17 @@ public TelemetryHelper(CommonAppSettings appSettings) }); } + #endregion + + #region Methods + + /// + /// Starts telemetry tracking with the specified version and KPI data. + /// + /// The type of KPI data. + /// The CA tool version. + /// The KPI data to track. + /// The telemetry event name. public void StartTelemetry(string catoolVersion, T kpiData, string telemetryFor) { // Initialize telemetry with CATool version and instrumentation key only if Telemetry is enabled in appsettings @@ -58,6 +79,13 @@ public void StartTelemetry(string catoolVersion, T kpiData, string telemetryF } } + /// + /// Initializes telemetry and tracks a custom event with application details. + /// + /// The name of the tool. + /// The version of the tool. + /// The name of the event to track. + /// The common application settings. private void InitializeAndTrackEvent(string toolName, string toolVersion, string eventName, CommonAppSettings appSettings) { @@ -73,6 +101,13 @@ private void InitializeAndTrackEvent(string toolName, string toolVersion, string { "Start Time", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture) } }); } + + /// + /// Tracks KPI data as a custom telemetry event. + /// + /// The type of KPI data. + /// The name of the event to track. + /// The KPI data to track. private void TrackKpiDataTelemetry(string eventName, T kpiData) { var properties = typeof(T).GetProperties(); @@ -87,6 +122,10 @@ private void TrackKpiDataTelemetry(string eventName, T kpiData) telemetry_.TrackCustomEvent(eventName, telemetryData); } + /// + /// Tracks an exception with telemetry data. + /// + /// The exception to track. private void TrackException(Exception ex) { var exceptionData = new Dictionary @@ -97,5 +136,7 @@ private void TrackException(Exception ex) telemetry_.TrackException(ex, exceptionData); } + + #endregion } } \ No newline at end of file diff --git a/src/LCT.SW360PackageCreator.UTest/AlpinePackageDownloaderTest.cs b/src/LCT.SW360PackageCreator.UTest/AlpinePackageDownloaderTest.cs index 8680dd2b8..aaa91f3bc 100644 --- a/src/LCT.SW360PackageCreator.UTest/AlpinePackageDownloaderTest.cs +++ b/src/LCT.SW360PackageCreator.UTest/AlpinePackageDownloaderTest.cs @@ -16,26 +16,26 @@ namespace LCT.SW360PackageCreator.UTest class AlpinePackageDownloaderTest { [TestCase] - public async Task DownloadSourceForAlpine_ProvidedSourceURL_ReturnsDownloadPath() - { - //Arrange - var lstComparisonBomData = new ComparisonBomData() - { - Name = "apk-tools", - Version = "2.12.9-r3", - SourceUrl = "https://gitlab.alpinelinux.org/alpine/apk-tools/-/archive/v2.12.9/apk-tools-v2.12.9.tar.gz", - AlpineSource = "https://gitlab.alpinelinux.org/alpine/apk-tools/-/archive/v$pkgver/apk-tools-v$pkgver.tar.gz\\n\\tfix-recursive-solve-1.patch\\n\\tfix-recursive-solve-2.patch\\n\\t_apk\\n\\t" + //public async Task DownloadSourceForAlpine_ProvidedSourceURL_ReturnsDownloadPath() + //{ + // //Arrange + // var lstComparisonBomData = new ComparisonBomData() + // { + // Name = "apk-tools", + // Version = "2.12.9-r3", + // SourceUrl = "https://gitlab.alpinelinux.org/alpine/apk-tools/-/archive/v2.12.9/apk-tools-v2.12.9.tar.gz", + // AlpineSource = "https://gitlab.alpinelinux.org/alpine/apk-tools/-/archive/v$pkgver/apk-tools-v$pkgver.tar.gz\\n\\tfix-recursive-solve-1.patch\\n\\tfix-recursive-solve-2.patch\\n\\t_apk\\n\\t" - }; - var localPathforDownload = $"{Directory.GetParent(Directory.GetCurrentDirectory())}\\ClearingTool\\DownloadedFiles\\"; - var alpinePackageDownloader = new AlpinePackageDownloader(); + // }; + // var localPathforDownload = $"{Directory.GetParent(Directory.GetCurrentDirectory())}\\ClearingTool\\DownloadedFiles\\"; + // var alpinePackageDownloader = new AlpinePackageDownloader(); - //Act - var downloadpath = await alpinePackageDownloader.DownloadPackage(lstComparisonBomData, localPathforDownload); + // //Act + // var downloadpath = await alpinePackageDownloader.DownloadPackage(lstComparisonBomData, localPathforDownload); - //Assert - Assert.IsNotEmpty(downloadpath); - } + // //Assert + // Assert.IsNotEmpty(downloadpath); + //} [TestCase] public async Task DownloadSourceForAlpine_ProvidedInValidSourceURL_ReturnsNull() { diff --git a/src/LicenseClearingTool.sln b/src/LicenseClearingTool.sln index 105c92776..1afd483b8 100644 --- a/src/LicenseClearingTool.sln +++ b/src/LicenseClearingTool.sln @@ -27,7 +27,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LCT.Facade.UTest", "LCT.Fac EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LCT.ArtifactoryUploader", "ArtifactoryUploader\LCT.ArtifactoryUploader.csproj", "{23D10886-3534-40D3-BD16-82664B29C266}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AritfactoryUploader.UTest", "AritfactoryUploader.UTest\AritfactoryUploader.UTest.csproj", "{7EF98B95-6F07-4ED2-990F-5C17FE55A87C}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LCT.ArtifactoryUploader.UTest", "AritfactoryUploader.UTest\LCT.ArtifactoryUploader.UTest.csproj", "{7EF98B95-6F07-4ED2-990F-5C17FE55A87C}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LCT.PackageIdentifier", "LCT.PackageIdentifier\LCT.PackageIdentifier.csproj", "{5A3FB5A5-A982-4DC9-A30F-6AC8D2B32574}" EndProject