diff --git a/src/LCT.APICommunications/Interfaces/ISW360APICommunication.cs b/src/LCT.APICommunications/Interfaces/ISW360APICommunication.cs index 12cd45b6..372863b6 100644 --- a/src/LCT.APICommunications/Interfaces/ISW360APICommunication.cs +++ b/src/LCT.APICommunications/Interfaces/ISW360APICommunication.cs @@ -40,5 +40,6 @@ public interface ISw360ApiCommunication string AttachComponentSourceToSW360(AttachReport attachReport); void DownloadAttachmentUsingWebClient(string attachmentDownloadLink, string fileName); Task GetComponentDetailsByUrl(string componentLink); + Task GetAllReleasesWithAllData(int page, int pageEntries); } } diff --git a/src/LCT.APICommunications/SW360Apicommunication.cs b/src/LCT.APICommunications/SW360Apicommunication.cs index b6a631c4..8bdbf405 100644 --- a/src/LCT.APICommunications/SW360Apicommunication.cs +++ b/src/LCT.APICommunications/SW360Apicommunication.cs @@ -313,6 +313,12 @@ public async Task GetComponentUsingName(string componentNam string url = $"{sw360ComponentApi}{ApiConstant.ComponentNameUrl}{componentName}"; return await httpClient.GetAsync(url); } + public async Task GetAllReleasesWithAllData(int page, int pageEntries) + { + HttpClient httpClient = GetHttpClient(); + string url = $"{sw360ReleaseApi}?page={page}&allDetails=true&page_entries={pageEntries}"; + return await httpClient.GetAsync(url); + } #endregion #region PRIVATE METHODS diff --git a/src/LCT.Common/CommonAppSettings.cs b/src/LCT.Common/CommonAppSettings.cs index d4d5eb05..e7db107e 100644 --- a/src/LCT.Common/CommonAppSettings.cs +++ b/src/LCT.Common/CommonAppSettings.cs @@ -172,7 +172,8 @@ public string URL } set { - if (AppDomain.CurrentDomain.FriendlyName.Contains("SW360PackageCreator")) + if (!AppDomain.CurrentDomain.FriendlyName.Contains("PackageIdentifier") && + !AppDomain.CurrentDomain.FriendlyName.Contains("ArtifactoryUploader")) { if (string.IsNullOrEmpty(value)) { diff --git a/src/LCT.Common/Constants/Dataconstant.cs b/src/LCT.Common/Constants/Dataconstant.cs index da50c646..c39b680d 100644 --- a/src/LCT.Common/Constants/Dataconstant.cs +++ b/src/LCT.Common/Constants/Dataconstant.cs @@ -68,6 +68,8 @@ public static class Dataconstant public const string Cdx_Siemensfilename = "internal:siemens:clearing:siemens:filename"; public const string Cdx_SiemensDirect = "internal:siemens:clearing:siemens:direct"; public const string Cdx_ExcludeComponent = "internal:siemens:clearing:sw360:exclude"; + public const string ProductionFossologyURL = "automation.fossology"; + public const string StageFossologyURL = "stage.fossology"; public static Dictionary PurlCheck() { diff --git a/src/LCT.Common/PipelineArtifactUploader.cs b/src/LCT.Common/PipelineArtifactUploader.cs index 64c5320f..184b733c 100644 --- a/src/LCT.Common/PipelineArtifactUploader.cs +++ b/src/LCT.Common/PipelineArtifactUploader.cs @@ -26,10 +26,10 @@ public static void UploadArtifacts() /// public static void UploadLogs() { - EnvironmentType envType = RuntimeEnvironment.GetEnvironment(); - LogManager.Shutdown(); + EnvironmentType envType = RuntimeEnvironment.GetEnvironment(); if (envType == EnvironmentType.AzurePipeline && !string.IsNullOrEmpty(Log4Net.CatoolLogPath) && File.Exists(Log4Net.CatoolLogPath)) - { + { + LogManager.Shutdown(); Console.WriteLine($"##vso[artifact.upload containerfolder={LogContainerFolderName};artifactname={LogArtifactFolderName}]{Log4Net.CatoolLogPath}"); } else if (envType == EnvironmentType.Unknown) @@ -44,7 +44,7 @@ public static void UploadLogs() /// public static void UploadBom() { - EnvironmentType envType = RuntimeEnvironment.GetEnvironment(); + EnvironmentType envType = RuntimeEnvironment.GetEnvironment(); if (envType == EnvironmentType.AzurePipeline && !string.IsNullOrEmpty(FileOperations.CatoolBomFilePath) && File.Exists(FileOperations.CatoolBomFilePath)) { Console.WriteLine($"##vso[artifact.upload containerfolder={BomContainerFolderName};artifactname={BomArtifactFolderName}]{FileOperations.CatoolBomFilePath}"); diff --git a/src/LCT.Facade/Interfaces/ISW360ApicommunicationFacade.cs b/src/LCT.Facade/Interfaces/ISW360ApicommunicationFacade.cs index 9b96fd75..8b766303 100644 --- a/src/LCT.Facade/Interfaces/ISW360ApicommunicationFacade.cs +++ b/src/LCT.Facade/Interfaces/ISW360ApicommunicationFacade.cs @@ -43,5 +43,6 @@ public interface ISW360ApicommunicationFacade Task UpdateLinkedRelease(string projectId, string releaseId, UpdateLinkedRelease updateLinkedRelease); Task GetReleaseByExternalId(string purlId,string externalIdKey = ""); Task GetComponentByExternalId(string purlId, string externalIdKey = ""); + Task GetAllReleasesWithAllData(int page, int pageEntries); } } diff --git a/src/LCT.Facade/SW360ApicommunicationFacade.cs b/src/LCT.Facade/SW360ApicommunicationFacade.cs index fdf51bf3..3574f3af 100644 --- a/src/LCT.Facade/SW360ApicommunicationFacade.cs +++ b/src/LCT.Facade/SW360ApicommunicationFacade.cs @@ -195,5 +195,9 @@ public Task GetComponentByExternalId(string purlId, string { return m_sw360ApiCommunication.GetComponentByExternalId(purlId, externalIdKey); } + public Task GetAllReleasesWithAllData(int page, int pageEntries) + { + return m_sw360ApiCommunication.GetAllReleasesWithAllData(page, pageEntries); + } } } diff --git a/src/LCT.SW360PackageCreator.UTest/CreatorValidatorTest.cs b/src/LCT.SW360PackageCreator.UTest/CreatorValidatorTest.cs index b41b65fa..2f0593b4 100644 --- a/src/LCT.SW360PackageCreator.UTest/CreatorValidatorTest.cs +++ b/src/LCT.SW360PackageCreator.UTest/CreatorValidatorTest.cs @@ -13,6 +13,16 @@ using LCT.Common; using System.Threading.Tasks; using LCT.APICommunications.Model; +using LCT.Facade.Interfaces; +using LCT.APICommunications.Model.Foss; +using Newtonsoft.Json; +using System.Net.Http; +using LCT.Common.Interface; +using System.Net; +using System.Threading; +using Moq.Protected; +using System.Security.Policy; +using System.Reflection; namespace LCT.SW360PackageCreator.UTest { @@ -20,9 +30,21 @@ namespace LCT.SW360PackageCreator.UTest public class CreatorValidatorTest { public Mock mockISw360ProjectService; + private Mock mockISW360ApicommunicationFacade; + private Mock mockISW360Service; + private Mock mockISw360CreatorService; + private Mock mockEnvironmentHelper; + private Mock mockHttpMessageHandler; + private HttpClient httpClient; public CreatorValidatorTest() { mockISw360ProjectService = new Mock(MockBehavior.Strict); + mockISW360ApicommunicationFacade = new Mock(); + mockISW360Service = new Mock(); + mockISw360CreatorService = new Mock(); + mockEnvironmentHelper = new Mock(); + mockHttpMessageHandler = new Mock(); + httpClient = new HttpClient(mockHttpMessageHandler.Object); } [TestCase] @@ -30,7 +52,7 @@ public async Task ValidateAppSettings_TestPositive() { //Arrange string projectName = "Test"; - ProjectReleases projectReleases=new ProjectReleases(); + ProjectReleases projectReleases = new ProjectReleases(); var CommonAppSettings = new CommonAppSettings() { SW360 = new SW360() @@ -42,7 +64,7 @@ public async Task ValidateAppSettings_TestPositive() .ReturnsAsync(projectName); //Act - await CreatorValidator.ValidateAppSettings(CommonAppSettings, mockISw360ProjectService.Object,projectReleases); + await CreatorValidator.ValidateAppSettings(CommonAppSettings, mockISw360ProjectService.Object, projectReleases); //Assert mockISw360ProjectService.Verify(x => x.GetProjectNameByProjectIDFromSW360(It.IsAny(), It.IsAny(), projectReleases), Times.AtLeastOnce); @@ -59,10 +81,10 @@ public async Task ValidateAppSettings_OnClosedProject_EndsTheApplication() { SW360 = new SW360() { - ProjectName= "Test" + ProjectName = "Test" } }; - + mockISw360ProjectService.Setup(x => x.GetProjectNameByProjectIDFromSW360(It.IsAny(), It.IsAny(), projectReleases)) .ReturnsAsync(projectName); @@ -82,9 +104,9 @@ public void ValidateAppSettings_TestNegative() ProjectReleases projectReleases = new ProjectReleases(); var CommonAppSettings = new CommonAppSettings() { - SW360=new SW360() + SW360 = new SW360() }; - mockISw360ProjectService.Setup(x => x.GetProjectNameByProjectIDFromSW360(It.IsAny(), It.IsAny(),projectReleases)) + mockISw360ProjectService.Setup(x => x.GetProjectNameByProjectIDFromSW360(It.IsAny(), It.IsAny(), projectReleases)) .ReturnsAsync(projectName); //Act @@ -93,6 +115,170 @@ public void ValidateAppSettings_TestNegative() Assert.ThrowsAsync(() => CreatorValidator.ValidateAppSettings(CommonAppSettings, mockISw360ProjectService.Object, projectReleases)); } + [Test] + public async Task TriggerFossologyValidation_TestPositive() + { + // Arrange + var appSettings = new CommonAppSettings() + { + SW360 = new SW360() + { + URL = "https://sw360.example.com" + } + }; + + var responseBody = "{\"_embedded\":{\"sw360:releases\":[{\"id\":\"a3c5c9d1dd469d668433fb147c01bad2\",\"name\":\"HC-Test Pugixml\",\"version\":\"V1.2\",\"clearingState\":\"APPROVED\",\"_embedded\":{\"sw360:attachments\":[[{\"filename\":\"Protocol_Pugixml - 1.2.doc\"}]]},\"_links\":{\"self\":{\"href\":\"https://sw360.siemens.com/resource/api/releases/a3c5c9d1dd469d668433fb147c01bad2\"}}}]},\"page\":{\"totalPages\":1}}"; + var releasesInfo = new ReleasesInfo + { + Name = "TestRelease", + Version = "1.0", + ClearingState = "APPROVED" + }; + var fossTriggerStatus = new FossTriggerStatus + { + Links = new Links + { + Self = new Self + { + Href = "https://fossology.example.com" + } + } + }; + + var triggerStatusResponse = JsonConvert.SerializeObject(fossTriggerStatus); + + mockISW360ApicommunicationFacade.Setup(x => x.GetAllReleasesWithAllData(It.IsAny(), It.IsAny())).ReturnsAsync(new HttpResponseMessage + { + Content = new StringContent(responseBody) + }); + + mockISW360ApicommunicationFacade.Setup(x => x.TriggerFossologyProcess(It.IsAny(), It.IsAny())).ReturnsAsync(triggerStatusResponse); + + mockISw360CreatorService.Setup(x => x.TriggerFossologyProcessForValidation(It.IsAny(), It.IsAny())).ReturnsAsync(fossTriggerStatus); + + // Act + await CreatorValidator.TriggerFossologyValidation(appSettings, mockISW360ApicommunicationFacade.Object); + + // Assert + mockISW360ApicommunicationFacade.Verify(x => x.GetAllReleasesWithAllData(It.IsAny(), It.IsAny()), Times.Once); + mockISW360ApicommunicationFacade.Verify(x => x.TriggerFossologyProcess(It.IsAny(), It.IsAny()), Times.Once); + } + [Test] + public async Task FossologyUrlValidation_ValidUrl_ReturnsTrue() + { + // Arrange + var appSettings = new CommonAppSettings() + { + SW360 = new SW360() + { + Fossology = new Fossology() + { + URL = "https://stage.fossology.url" + } + } + }; + var responseMessage = new HttpResponseMessage(HttpStatusCode.OK); + mockHttpMessageHandler + .Protected() + .Setup>( + "SendAsync", + ItExpr.IsAny(), + ItExpr.IsAny() + ) + .ReturnsAsync(responseMessage); + // Act + var result = await CreatorValidator.FossologyUrlValidation(appSettings, httpClient, mockEnvironmentHelper.Object); + + // Assert + Assert.IsTrue(result); + } + + [Test] + public async Task FossologyUrlValidation_InvalidUrl_ReturnsFalse() + { + // Arrange + var appSettings = new CommonAppSettings() + { + SW360 = new SW360() + { + Fossology = new Fossology() + { + URL = "https://invalid.fossology.url" + } + } + }; + + var responseMessage = new HttpResponseMessage(HttpStatusCode.NotFound); + mockHttpMessageHandler + .Protected() + .Setup>( + "SendAsync", + ItExpr.IsAny(), + ItExpr.IsAny() + ) + .ReturnsAsync(responseMessage); + + // Act + var result = await CreatorValidator.FossologyUrlValidation(appSettings, httpClient, mockEnvironmentHelper.Object); + + // Assert + Assert.IsFalse(result); + } + + + [Test] + public async Task FossologyUrlValidation_InvalidUri_ThrowsException() + { + // Arrange + var appSettings = new CommonAppSettings() + { + SW360 = new SW360() + { + Fossology = new Fossology() + { + URL = "invalid_uri" + } + } + }; + + var result = await CreatorValidator.FossologyUrlValidation(appSettings, httpClient, mockEnvironmentHelper.Object); + + // Assert + Assert.IsFalse(result); + } + + [Test] + public async Task FossologyUrlValidation_HttpRequestException_ReturnsFalse() + { + // Arrange + var appSettings = new CommonAppSettings() + { + SW360 = new SW360() + { + Fossology = new Fossology() + { + URL = "https://valid.fossology.url" + } + } + }; + + mockHttpMessageHandler + .Protected() + .Setup>( + "SendAsync", + ItExpr.IsAny(), + ItExpr.IsAny() + ) + .ThrowsAsync(new HttpRequestException()); + + // Act + var result = await CreatorValidator.FossologyUrlValidation(appSettings, httpClient, mockEnvironmentHelper.Object); + + // Assert + Assert.IsFalse(result); + } + + } } diff --git a/src/LCT.SW360PackageCreator/CreatorValidator.cs b/src/LCT.SW360PackageCreator/CreatorValidator.cs index 5168d967..fa2614b3 100644 --- a/src/LCT.SW360PackageCreator/CreatorValidator.cs +++ b/src/LCT.SW360PackageCreator/CreatorValidator.cs @@ -11,6 +11,19 @@ using LCT.APICommunications.Model; using log4net; using System.Reflection; +using LCT.Common.Interface; +using LCT.APICommunications.Model.Foss; +using LCT.APICommunications; +using LCT.Facade.Interfaces; +using LCT.Services; +using log4net.Core; +using Newtonsoft.Json; +using System; +using System.Net.Http; +using LCT.SW360PackageCreator.Model; +using System.Linq; +using LCT.Common.Constants; +using LCT.Facade; namespace LCT.SW360PackageCreator @@ -21,9 +34,10 @@ namespace LCT.SW360PackageCreator public static class CreatorValidator { static readonly ILog Logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static IEnvironmentHelper environmentHelper =new EnvironmentHelper(); public static async Task ValidateAppSettings(CommonAppSettings appSettings, ISw360ProjectService sw360ProjectService, ProjectReleases projectReleases) { - string sw360ProjectName = await sw360ProjectService.GetProjectNameByProjectIDFromSW360(appSettings.SW360.ProjectID, appSettings.SW360.ProjectName,projectReleases); + string sw360ProjectName = await sw360ProjectService.GetProjectNameByProjectIDFromSW360(appSettings.SW360.ProjectID, appSettings.SW360.ProjectName, projectReleases); if (string.IsNullOrEmpty(sw360ProjectName)) { @@ -41,5 +55,165 @@ public static async Task ValidateAppSettings(CommonAppSettings appSettings, } return 0; } + public static async Task TriggerFossologyValidation(CommonAppSettings appSettings, ISW360ApicommunicationFacade sW360ApicommunicationFacade) + { + ISW360CommonService sw360CommonService = new SW360CommonService(sW360ApicommunicationFacade); + ISw360CreatorService sw360CreatorService = new Sw360CreatorService(sW360ApicommunicationFacade, sw360CommonService); + ISW360Service sw360Service = new Sw360Service(sW360ApicommunicationFacade, sw360CommonService, environmentHelper); + + try + { + int page = 0; + int pageEntries = 40; + bool validReleaseFound = false; + ReleasesAllDetails.Sw360Release validRelease = null; + int pageCount = 0; + while (!validReleaseFound && pageCount < 10) + { + ReleasesAllDetails releaseResponse = await GetAllReleasesDetails(sW360ApicommunicationFacade,page,pageEntries); + + if (releaseResponse != null) + { + validRelease = releaseResponse?.Embedded?.Sw360releases?.FirstOrDefault(release => release?.ClearingState == "APPROVED" && + release?.AllReleasesEmbedded?.Sw360attachments != null && + release.AllReleasesEmbedded.Sw360attachments.Any(attachments => attachments.Count != 0)); + + if (validRelease != null) + { + validReleaseFound = true; + } + else + { + int currentPage = page; + int totalPages = (int)(releaseResponse?.Page?.TotalPages); + if (currentPage < totalPages - 1) + { + page = currentPage + 1; + pageCount++; + } + else + { + break; + } + } + } + else + { + Logger.Debug($"TriggerFossologyValidation():Fossology URl validation Failed"); + } + } + + if (validReleaseFound) + { + var releaseUrl = validRelease?.Links?.Self?.Href; + var releaseId=string.Empty; + if (releaseUrl != null) + releaseId = CommonHelper.GetSubstringOfLastOccurance(releaseUrl, "/"); + string sw360link = $"{validRelease?.Name}:{validRelease?.Version}:{appSettings?.SW360?.URL}{ApiConstant.Sw360ReleaseUrlApiSuffix}" + + $"{releaseId}#/tab-Summary"; + FossTriggerStatus fossResult = await sw360CreatorService.TriggerFossologyProcessForValidation(releaseId, sw360link); + if (!string.IsNullOrEmpty(fossResult?.Links?.Self?.Href)) + { + Logger.Debug($"TriggerFossologyValidation():SW360 Fossology Process validation successfull!!"); + } + } + else + { + Logger.Debug($"TriggerFossologyValidation():Fossology URl validation Failed"); + } + + } + catch (AggregateException ex) + { + Logger.Debug($"\tError in TriggerFossologyValidation--{ex}"); + Logger.Error($"Trigger fossology process failed.Please check fossology configuration in sw360"); + environmentHelper.CallEnvironmentExit(-1); + } + } + private static async Task GetAllReleasesDetails(ISW360ApicommunicationFacade sW360ApicommunicationFacade, int page, int pageEntries) + { + ReleasesAllDetails releaseResponse = null; + try + { + var responseData = await sW360ApicommunicationFacade.GetAllReleasesWithAllData(page, pageEntries); + string response = responseData?.Content?.ReadAsStringAsync()?.Result ?? string.Empty; + releaseResponse = JsonConvert.DeserializeObject(response); + } + catch (HttpRequestException ex) + { + Logger.Debug($"GetAllReleasesDetails():", ex); + } + catch (InvalidOperationException ex) + { + Logger.Debug($"GetAllReleasesDetails():", ex); + } + catch (UriFormatException ex) + { + Logger.Debug($"GetAllReleasesDetails():", ex); + } + catch (TaskCanceledException ex) + { + Logger.Debug($"GetAllReleasesDetails():", ex); + } + + return releaseResponse; + } + public static async Task FossologyUrlValidation(CommonAppSettings appSettings, HttpClient client, IEnvironmentHelper environmentHelper) + { + string url = appSettings.SW360.Fossology.URL.ToLower(); + string prodFossUrl = Dataconstant.ProductionFossologyURL.ToLower(); + string stageFossUrl = Dataconstant.StageFossologyURL.ToLower(); + + if (string.IsNullOrEmpty(appSettings.SW360.Fossology.URL)) + { + Logger.Error($"Fossology URL is not provided ,Please make sure to add Fossologyurl in appsettings.."); + Logger.Debug($"FossologyUrlValidation() : Fossology url not provided in appsettings"); + environmentHelper.CallEnvironmentExit(-1); + } + else if (Uri.IsWellFormedUriString(appSettings.SW360.Fossology.URL, UriKind.Absolute)) + { + if (url.Contains(prodFossUrl) || url.Contains(stageFossUrl)) + { + // Send GET request to validate Fossology URL + try + { + HttpResponseMessage response = await client.GetAsync(new Uri(appSettings.SW360.Fossology.URL)); + if (response.IsSuccessStatusCode) + { + // Fossology URL is valid + return true; + } + else + { + // Fossology URL is not valid + Logger.Error($"Fossology URL is not valid ,please make sure to add valid fossologyurl in appsettings.."); + Logger.Debug($"FossologyUrlValidation() : Fossology URL is not valid."); + environmentHelper.CallEnvironmentExit(-1); + } + } + catch (HttpRequestException ex) + { + // Fossology URL is not valid + Logger.Error($"Fossology URL is not working ,please check once try again...."); + Logger.Debug($"FossologyUrlValidation() : Fossology URL is not valid.{ex}"); + environmentHelper.CallEnvironmentExit(-1); + } + } + else + { + Logger.Debug($"FossologyUrlValidation() : Fossology URL is not valid"); + Logger.Error($"Fossology URL is not valid ,please check once try again...."); + environmentHelper.CallEnvironmentExit(-1); + } + } + else + { + Logger.Error($"Fossology URL is not provided ,Please make sure to add fossologyurl in appsettings.."); + Logger.Debug($"FossologyUrlValidation() : Fossologyurl not provided in appsettings"); + environmentHelper.CallEnvironmentExit(-1); + } + return false; + } + } } diff --git a/src/LCT.SW360PackageCreator/Model/ReleasesAllDetails.cs b/src/LCT.SW360PackageCreator/Model/ReleasesAllDetails.cs new file mode 100644 index 00000000..7b222dc2 --- /dev/null +++ b/src/LCT.SW360PackageCreator/Model/ReleasesAllDetails.cs @@ -0,0 +1,68 @@ +// -------------------------------------------------------------------------------------------------------------------- +// SPDX-FileCopyrightText: 2025 Siemens AG +// +// SPDX-License-Identifier: MIT +// -------------------------------------------------------------------------------------------------------------------- + +using Newtonsoft.Json; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using static LCT.SW360PackageCreator.Model.ReleasesAllDetails; + +namespace LCT.SW360PackageCreator.Model +{ + public class ReleasesAllDetails + { + [ExcludeFromCodeCoverage] + [JsonProperty("_embedded")] + public AllReleasesEmbedded Embedded { get; set; } + [JsonProperty("page")] + public Pagination Page { get; set; } + public class AllReleasesEmbedded + { + [JsonProperty("sw360:releases")] + public List Sw360releases { get; set; } + + [JsonProperty("sw360:attachments")] + public List> Sw360attachments { get; set; } + + } + public class Attachment + { + [JsonProperty("filename")] + public string Filename { get; set; } + + } + public class Links + { + [JsonProperty("self")] + public Self Self { get; set; } + + } + public class Self + { + [JsonProperty("href")] + public string Href { get; set; } + } + public class Sw360Release + { + [JsonProperty("name")] + public string Name { get; set; } + [JsonProperty("version")] + public string Version { get; set; } + [JsonProperty("clearingState")] + public string ClearingState { get; set; } + [JsonProperty("_links")] + public Links Links { get; set; } + [JsonProperty("_embedded")] + public AllReleasesEmbedded AllReleasesEmbedded { get; set; } + + } + public class Pagination + { + [JsonProperty("totalPages")] + public int TotalPages { get; set; } + + } + } +} diff --git a/src/LCT.SW360PackageCreator/Program.cs b/src/LCT.SW360PackageCreator/Program.cs index 83c977db..80638f93 100644 --- a/src/LCT.SW360PackageCreator/Program.cs +++ b/src/LCT.SW360PackageCreator/Program.cs @@ -21,6 +21,7 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; +using System.Net.Http; using System.Reflection; using System.Runtime.InteropServices; using System.Threading.Tasks; @@ -36,8 +37,7 @@ public class Program { public static Stopwatch CreatorStopWatch { get; set; } private static bool m_Verbose = false; - private static readonly ILog Logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private static IEnvironmentHelper environmentHelper; + private static readonly ILog Logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); protected Program() { } static async Task Main(string[] args) @@ -49,6 +49,7 @@ static async Task Main(string[] args) m_Verbose = true; ISettingsManager settingsManager = new SettingsManager(); + EnvironmentHelper environmentHelper = new EnvironmentHelper(); CommonAppSettings appSettings = settingsManager.ReadConfiguration(args, FileConstant.appSettingFileName); ISW360ApicommunicationFacade sW360ApicommunicationFacade; ISw360ProjectService sw360ProjectService= Getsw360ProjectServiceObject(appSettings, out sW360ApicommunicationFacade); @@ -56,13 +57,13 @@ static async Task Main(string[] args) // do not change the order of getting ca tool information CatoolInfo caToolInformation = GetCatoolVersionFromProjectfile(); Log4Net.CatoolCurrentDirectory = Directory.GetParent(caToolInformation.CatoolRunningLocation).FullName; - + string FolderPath = InitiateLogger(appSettings); settingsManager.CheckRequiredArgsToRun(appSettings, "Creator"); int isValid = await CreatorValidator.ValidateAppSettings(appSettings, sw360ProjectService, projectReleases); + if (isValid == -1) { - environmentHelper = new EnvironmentHelper(); environmentHelper.CallEnvironmentExit(-1); } @@ -88,6 +89,13 @@ static async Task Main(string[] args) if (appSettings.IsTestMode) Logger.Logger.Log(null, Level.Notice, $"\tMode\t\t\t --> {appSettings.Mode}\n", null); + //Validate Fossology Url + if (appSettings.SW360.Fossology.EnableTrigger) + { + HttpClient client = new HttpClient(); + if (await CreatorValidator.FossologyUrlValidation(appSettings,client, environmentHelper)) + await CreatorValidator.TriggerFossologyValidation(appSettings, sW360ApicommunicationFacade); + } await InitiatePackageCreatorProcess(appSettings, sw360ProjectService, sW360ApicommunicationFacade); Logger.Logger.Log(null, Level.Notice, $"End of Package Creator execution: {DateTime.Now}\n", null); @@ -96,6 +104,7 @@ static async Task Main(string[] args) PipelineArtifactUploader.UploadArtifacts(); } + private static CatoolInfo GetCatoolVersionFromProjectfile() { CatoolInfo catoolInfo = new CatoolInfo(); diff --git a/src/LCT.Services/Interface/ISW360CreatorService.cs b/src/LCT.Services/Interface/ISW360CreatorService.cs index c53c3a32..0fdedede 100644 --- a/src/LCT.Services/Interface/ISW360CreatorService.cs +++ b/src/LCT.Services/Interface/ISW360CreatorService.cs @@ -44,5 +44,6 @@ Task CreateReleaseForComponent( Task UpdatePurlIdForExistingRelease(ComparisonBomData cbomData, string releaseId, ReleasesInfo releasesInfo = null); Task UdpateSW360ReleaseContent(Components component, string fossUrl); + Task TriggerFossologyProcessForValidation(string releaseId, string sw360link); } } diff --git a/src/LCT.Services/Sw360CreatorService.cs b/src/LCT.Services/Sw360CreatorService.cs index cc4d2df7..30b93e1e 100644 --- a/src/LCT.Services/Sw360CreatorService.cs +++ b/src/LCT.Services/Sw360CreatorService.cs @@ -9,6 +9,7 @@ using LCT.APICommunications.Model.Foss; using LCT.Common; using LCT.Common.Constants; +using LCT.Common.Interface; using LCT.Common.Model; using LCT.Facade.Interfaces; using LCT.Services.Interface; @@ -38,6 +39,7 @@ public class Sw360CreatorService : ISw360CreatorService static readonly ILog Logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); readonly ISW360ApicommunicationFacade m_SW360ApiCommunicationFacade; readonly ISW360CommonService m_SW360CommonService; + private static IEnvironmentHelper environmentHelper; public Sw360CreatorService(ISW360ApicommunicationFacade sw360ApiCommunicationFacade) { @@ -779,5 +781,40 @@ private async Task GetUpdateReleaseContent(string r return updateRelease; } + public async Task TriggerFossologyProcessForValidation(string releaseId, string sw360link) + { + environmentHelper = new EnvironmentHelper(); + FossTriggerStatus fossTriggerStatus = null; + try + { + string triggerStatus = await m_SW360ApiCommunicationFacade.TriggerFossologyProcess(releaseId, sw360link); + fossTriggerStatus = JsonConvert.DeserializeObject(triggerStatus); + } + catch (HttpRequestException ex) + { + Logger.Debug($"TriggerFossologyProcessForValidation():", ex); + Logger.Error($"Fossology process failed.Please check fossology configuration or Token in sw360"); + environmentHelper.CallEnvironmentExit(-1); + } + catch (InvalidOperationException ex) + { + Logger.Debug($"TriggerFossologyProcessForValidation():", ex); + Logger.Error($"Fossology process failed.Please check fossology configuration in sw360"); + environmentHelper.CallEnvironmentExit(-1); + } + catch (UriFormatException ex) + { + Logger.Debug($"TriggerFossologyProcessForValidation():", ex); + Logger.Error($"Fossology process failed.Please check fossology configuration in sw360"); + environmentHelper.CallEnvironmentExit(-1); + } + catch (TaskCanceledException ex) + { + Logger.Debug($"TriggerFossologyProcessForValidation():", ex); + Logger.Error($"Fossology process failed.Please check fossology configuration in sw360"); + environmentHelper.CallEnvironmentExit(-1); + } + return fossTriggerStatus; + } } } diff --git a/src/SW360IntegrationTest/Alpine/ComponentCreatorInitialAlpine.cs b/src/SW360IntegrationTest/Alpine/ComponentCreatorInitialAlpine.cs index b646ce3e..5a56f977 100644 --- a/src/SW360IntegrationTest/Alpine/ComponentCreatorInitialAlpine.cs +++ b/src/SW360IntegrationTest/Alpine/ComponentCreatorInitialAlpine.cs @@ -65,6 +65,8 @@ public void ComponentCreatorExe_ProvidedBOMFilePath_ReturnsSuccess() TestConstant.SW360ProjectID, testParameters.SW360ProjectID, TestConstant.SW360ProjectName, testParameters.SW360ProjectName, TestConstant.ProjectType,"ALPINE", + TestConstant.EnableFossologyTrigger,testParameters.FossologyTrigger, + TestConstant.FossologyURL, testParameters.FossUrl, TestConstant.Mode,""}), "Test to run component creator EXE execution"); } diff --git a/src/SW360IntegrationTest/Conan/ComponentCreatorInitialConan.cs b/src/SW360IntegrationTest/Conan/ComponentCreatorInitialConan.cs index ace5be1e..bb77ff20 100644 --- a/src/SW360IntegrationTest/Conan/ComponentCreatorInitialConan.cs +++ b/src/SW360IntegrationTest/Conan/ComponentCreatorInitialConan.cs @@ -55,6 +55,8 @@ public void TestComponentCreatorExe_Conan() TestConstant.SW360AuthTokenType, testParameters.SW360AuthTokenType, TestConstant.SW360ProjectID, testParameters.SW360ProjectID, TestConstant.SW360ProjectName, testParameters.SW360ProjectName, + TestConstant.FossologyURL, testParameters.FossUrl, + TestConstant.EnableFossologyTrigger,testParameters.FossologyTrigger, TestConstant.Mode,"" }), "Test to run Package Creator EXE execution"); diff --git a/src/SW360IntegrationTest/Debian/ComponentCreatorInitialDebian.cs b/src/SW360IntegrationTest/Debian/ComponentCreatorInitialDebian.cs index 435c1707..2e01672a 100644 --- a/src/SW360IntegrationTest/Debian/ComponentCreatorInitialDebian.cs +++ b/src/SW360IntegrationTest/Debian/ComponentCreatorInitialDebian.cs @@ -64,6 +64,8 @@ public void ComponentCreatorExe_ProvidedBOMFilePath_ReturnsSuccess() TestConstant.SW360ProjectID, testParameters.SW360ProjectID, TestConstant.SW360ProjectName, testParameters.SW360ProjectName, TestConstant.ProjectType,"DEBIAN", + TestConstant.FossologyURL, testParameters.FossUrl, + TestConstant.EnableFossologyTrigger,testParameters.FossologyTrigger, TestConstant.Mode,""}), "Test to run component creator EXE execution"); } diff --git a/src/SW360IntegrationTest/Maven/ComponentCreatorInitialMaven.cs b/src/SW360IntegrationTest/Maven/ComponentCreatorInitialMaven.cs index e8a6d33e..0a588dd5 100644 --- a/src/SW360IntegrationTest/Maven/ComponentCreatorInitialMaven.cs +++ b/src/SW360IntegrationTest/Maven/ComponentCreatorInitialMaven.cs @@ -65,6 +65,8 @@ public void ComponentCreatorExe_ProvidedBOMFilePath_ReturnsSuccess() TestConstant.SW360AuthTokenType, testParameters.SW360AuthTokenType, TestConstant.SW360ProjectID, testParameters.SW360ProjectID, TestConstant.SW360ProjectName, testParameters.SW360ProjectName, + TestConstant.FossologyURL, testParameters.FossUrl, + TestConstant.EnableFossologyTrigger,testParameters.FossologyTrigger, TestConstant.Mode,""}), "Test to run Package Creator EXE execution"); } diff --git a/src/SW360IntegrationTest/NPM/ComponentCreatorInitial.cs b/src/SW360IntegrationTest/NPM/ComponentCreatorInitial.cs index a2b84a08..aabba534 100644 --- a/src/SW360IntegrationTest/NPM/ComponentCreatorInitial.cs +++ b/src/SW360IntegrationTest/NPM/ComponentCreatorInitial.cs @@ -65,6 +65,7 @@ public void TestComponentCreatorExe() TestConstant.SW360AuthTokenType, testParameters.SW360AuthTokenType, TestConstant.SW360ProjectID, testParameters.SW360ProjectID, TestConstant.SW360ProjectName, testParameters.SW360ProjectName, + TestConstant.EnableFossologyTrigger,testParameters.FossologyTrigger, TestConstant.FossologyURL,testParameters.FossUrl }), "Test to run Package Creator EXE execution"); } diff --git a/src/SW360IntegrationTest/NPM/ComponentCreatorTestMode.cs b/src/SW360IntegrationTest/NPM/ComponentCreatorTestMode.cs index 8c8cc5e7..a564363e 100644 --- a/src/SW360IntegrationTest/NPM/ComponentCreatorTestMode.cs +++ b/src/SW360IntegrationTest/NPM/ComponentCreatorTestMode.cs @@ -63,6 +63,8 @@ public void TestComponentCreatorExe_TestMode() TestConstant.SW360AuthTokenType, testParameters.SW360AuthTokenType, TestConstant.SW360ProjectID, testParameters.SW360ProjectID, TestConstant.SW360ProjectName, testParameters.SW360ProjectName, + TestConstant.FossologyURL, testParameters.FossUrl, + TestConstant.EnableFossologyTrigger,testParameters.FossologyTrigger, TestConstant.Mode,"test" }), "Test to run Package Creator EXE execution"); diff --git a/src/SW360IntegrationTest/NPM/ComponentCreatorWithUpdatedComponents.cs b/src/SW360IntegrationTest/NPM/ComponentCreatorWithUpdatedComponents.cs index a0d7f3c0..c0dcdfe7 100644 --- a/src/SW360IntegrationTest/NPM/ComponentCreatorWithUpdatedComponents.cs +++ b/src/SW360IntegrationTest/NPM/ComponentCreatorWithUpdatedComponents.cs @@ -67,6 +67,8 @@ public void TestComponentCreatorExe() TestConstant.SW360AuthTokenType, testParameters.SW360AuthTokenType, TestConstant.SW360ProjectID, testParameters.SW360ProjectID, TestConstant.SW360ProjectName, testParameters.SW360ProjectName, + TestConstant.FossologyURL, testParameters.FossUrl, + TestConstant.EnableFossologyTrigger,testParameters.FossologyTrigger, TestConstant.Mode,"" }), "Test to run Package Creator EXE execution"); } diff --git a/src/SW360IntegrationTest/Nuget/ComponentCreatorInitialNuget.cs b/src/SW360IntegrationTest/Nuget/ComponentCreatorInitialNuget.cs index 0f556f27..e84eadad 100644 --- a/src/SW360IntegrationTest/Nuget/ComponentCreatorInitialNuget.cs +++ b/src/SW360IntegrationTest/Nuget/ComponentCreatorInitialNuget.cs @@ -65,6 +65,8 @@ public void ComponentCreatorExe_ProvidedBOMFilePath_ReturnsSuccess() TestConstant.SW360ProjectID, testParameters.SW360ProjectID, TestConstant.SW360ProjectName, testParameters.SW360ProjectName, TestConstant.ProjectType,"NUGET", + TestConstant.FossologyURL, testParameters.FossUrl, + TestConstant.EnableFossologyTrigger,testParameters.FossologyTrigger, TestConstant.Mode,""}), "Test to run Package Creator EXE execution"); } diff --git a/src/SW360IntegrationTest/Nuget/NugetTemplate/ComponentCreatorNugetTemplate.cs b/src/SW360IntegrationTest/Nuget/NugetTemplate/ComponentCreatorNugetTemplate.cs index 236a8a30..6c706b68 100644 --- a/src/SW360IntegrationTest/Nuget/NugetTemplate/ComponentCreatorNugetTemplate.cs +++ b/src/SW360IntegrationTest/Nuget/NugetTemplate/ComponentCreatorNugetTemplate.cs @@ -67,6 +67,8 @@ public void ComponentCreatorExe_ProvidedBOMFilePath_ReturnsSuccess() TestConstant.SW360ProjectID, testParameters.SW360ProjectID, TestConstant.SW360ProjectName, testParameters.SW360ProjectName, TestConstant.ProjectType,"NUGET", + TestConstant.FossologyURL, testParameters.FossUrl, + TestConstant.EnableFossologyTrigger,testParameters.FossologyTrigger, TestConstant.Mode,""}); Assert.IsTrue(value == 0 || value == 2, diff --git a/src/SW360IntegrationTest/Python/ComponentCreatorInitialPython.cs b/src/SW360IntegrationTest/Python/ComponentCreatorInitialPython.cs index 088ea1e7..020661c8 100644 --- a/src/SW360IntegrationTest/Python/ComponentCreatorInitialPython.cs +++ b/src/SW360IntegrationTest/Python/ComponentCreatorInitialPython.cs @@ -63,6 +63,8 @@ public void ComponentCreatorExe_ProvidedBOMFilePath_ReturnsSuccess() TestConstant.SW360AuthTokenType, testParameters.SW360AuthTokenType, TestConstant.SW360ProjectID, testParameters.SW360ProjectID, TestConstant.SW360ProjectName, testParameters.SW360ProjectName, + TestConstant.FossologyURL, testParameters.FossUrl, + TestConstant.EnableFossologyTrigger,testParameters.FossologyTrigger, TestConstant.Mode,""}); Assert.IsTrue(returnValue == 0 || returnValue == 2, "Test to run Package Creator EXE execution"); diff --git a/src/TestUtilities/TestConstant.cs b/src/TestUtilities/TestConstant.cs index ea1b1d99..f5898d45 100644 --- a/src/TestUtilities/TestConstant.cs +++ b/src/TestUtilities/TestConstant.cs @@ -31,7 +31,8 @@ public static class TestConstant public const string Sw360Token = "--SW360:Token"; public const string BomFilePath = "--Directory:BomFilePath"; public const string SW360URL = "--SW360:URL"; - public const string FossologyURL = "--Fossology:URL"; + public const string FossologyURL = "--SW360:Fossology:URL"; + public const string EnableFossologyTrigger = "--SW360:Fossology:EnableTrigger"; public const string SW360AuthTokenType = "--SW360:AuthTokenType"; public const string SW360ProjectName = "--SW360:ProjectName"; public const string SW360ProjectID = "--SW360:ProjectID"; diff --git a/src/TestUtilities/TestParam.cs b/src/TestUtilities/TestParam.cs index 05648096..b114a405 100644 --- a/src/TestUtilities/TestParam.cs +++ b/src/TestUtilities/TestParam.cs @@ -29,7 +29,7 @@ public class TestParam public string ThirdPartyDestinationRepoName { get; set; } public string InternalDestinationRepoName { get; set; } public string DevDestinationRepoName { get; set; } - + public string FossologyTrigger { get; set; } public TestParam() { SW360AuthTokenType = s_Config["SW360AuthTokenType"]; @@ -46,6 +46,7 @@ public TestParam() ThirdPartyDestinationRepoName = "npm-test"; InternalDestinationRepoName = "npm-test"; DevDestinationRepoName = "npm-test"; + FossologyTrigger = s_Config["EnableFossologyTrigger"]; } } } diff --git a/src/TestUtilities/TestParamAlpine.cs b/src/TestUtilities/TestParamAlpine.cs index c76a7a48..8ee53308 100644 --- a/src/TestUtilities/TestParamAlpine.cs +++ b/src/TestUtilities/TestParamAlpine.cs @@ -23,6 +23,7 @@ public class TestParamAlpine public string ArtifactoryUploadUser { get; set; } public string ArtifactoryUploadApiKey { get; set; } public string JfrogApi { get; set; } + public string FossologyTrigger { get; set; } public TestParamAlpine() { @@ -37,6 +38,7 @@ public TestParamAlpine() ArtifactoryUploadApiKey = s_Config["ArtifactoryUploadApiKey"]; JfrogApi = s_Config["JfrogApi"]; RemoveDevDependency = s_Config["RemoveDevDependency"]; + FossologyTrigger = s_Config["EnableFossologyTrigger"]; } } } diff --git a/src/TestUtilities/TestParamConan.cs b/src/TestUtilities/TestParamConan.cs index 7bd4ed14..9b15c95a 100644 --- a/src/TestUtilities/TestParamConan.cs +++ b/src/TestUtilities/TestParamConan.cs @@ -28,7 +28,7 @@ public class TestParamConan public string ThirdPartyDestinationRepoName { get; set; } public string InternalDestinationRepoName { get; set; } public string DevDestinationRepoName { get; set; } - + public string FossologyTrigger { get; set; } public TestParamConan() { SW360AuthTokenType = s_Config["SW360AuthTokenType"]; @@ -45,6 +45,7 @@ public TestParamConan() ThirdPartyDestinationRepoName = "conan-test"; InternalDestinationRepoName = "conan-test"; DevDestinationRepoName = "conan-test"; + FossologyTrigger = s_Config["EnableFossologyTrigger"]; } } } diff --git a/src/TestUtilities/TestParamDebian.cs b/src/TestUtilities/TestParamDebian.cs index 1f0d170b..e4aef5cb 100644 --- a/src/TestUtilities/TestParamDebian.cs +++ b/src/TestUtilities/TestParamDebian.cs @@ -23,6 +23,7 @@ public class TestParamDebian public string ArtifactoryUploadUser { get; set; } public string ArtifactoryUploadApiKey { get; set; } public string JfrogApi { get; set; } + public string FossologyTrigger { get; set; } public TestParamDebian() { @@ -37,6 +38,7 @@ public TestParamDebian() ArtifactoryUploadApiKey = s_Config["ArtifactoryUploadApiKey"]; JfrogApi = s_Config["JfrogApi"]; RemoveDevDependency = s_Config["RemoveDevDependency"]; + FossologyTrigger = s_Config["EnableFossologyTrigger"]; } } } diff --git a/src/TestUtilities/TestParamMaven.cs b/src/TestUtilities/TestParamMaven.cs index b268c3b3..6d72dc36 100644 --- a/src/TestUtilities/TestParamMaven.cs +++ b/src/TestUtilities/TestParamMaven.cs @@ -28,6 +28,7 @@ public class TestParamMaven public string ThirdPartyDestinationRepoName { get; set; } public string InternalDestinationRepoName { get; set; } public string DevDestinationRepoName { get; set; } + public string FossologyTrigger { get; set; } public TestParamMaven() { @@ -45,6 +46,7 @@ public TestParamMaven() ThirdPartyDestinationRepoName = "maven-test"; InternalDestinationRepoName = "maven-test"; DevDestinationRepoName = "maven-test"; + FossologyTrigger = s_Config["EnableFossologyTrigger"]; } } } diff --git a/src/TestUtilities/TestParamNuget.cs b/src/TestUtilities/TestParamNuget.cs index b8e9f958..ea3df7e7 100644 --- a/src/TestUtilities/TestParamNuget.cs +++ b/src/TestUtilities/TestParamNuget.cs @@ -32,6 +32,7 @@ public class TestParamNuget public string ThirdPartyDestinationRepoName { get; set; } public string InternalDestinationRepoName { get; set; } public string DevDestinationRepoName { get; set; } + public string FossologyTrigger { get; set; } public TestParamNuget() { @@ -49,6 +50,7 @@ public TestParamNuget() ThirdPartyDestinationRepoName = "nuget-test"; InternalDestinationRepoName = "nuget-test"; DevDestinationRepoName = "nuget-test"; + FossologyTrigger = s_Config["EnableFossologyTrigger"]; } } } diff --git a/src/TestUtilities/appSettingsSW360IntegrationTest.json b/src/TestUtilities/appSettingsSW360IntegrationTest.json index 10140cf8..56483e8c 100644 --- a/src/TestUtilities/appSettingsSW360IntegrationTest.json +++ b/src/TestUtilities/appSettingsSW360IntegrationTest.json @@ -1,6 +1,7 @@ { "Fossologyurl": "", "RemoveDevDependency": true, + "EnableFossologyTrigger": false, "SW360AuthTokenType": "Token", "SW360ProjectID": "036ec371847b4b199dd21c3494ccb108", "SW360ProjectName": "Test",