diff --git a/src/LCT.SW360PackageCreator.UTest/CreatorValidatorTest.cs b/src/LCT.SW360PackageCreator.UTest/CreatorValidatorTest.cs index b41b65fa..edc1cec8 100644 --- a/src/LCT.SW360PackageCreator.UTest/CreatorValidatorTest.cs +++ b/src/LCT.SW360PackageCreator.UTest/CreatorValidatorTest.cs @@ -13,6 +13,10 @@ 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; namespace LCT.SW360PackageCreator.UTest { @@ -20,9 +24,17 @@ namespace LCT.SW360PackageCreator.UTest public class CreatorValidatorTest { public Mock mockISw360ProjectService; + public Mock mockISW360ApicommunicationFacade; + public Mock mockISW360CommonService; + public Mock mockISw360CreatorService; + public Mock mockISW360Service; public CreatorValidatorTest() { mockISw360ProjectService = new Mock(MockBehavior.Strict); + mockISW360ApicommunicationFacade = new Mock(MockBehavior.Strict); + mockISW360CommonService = new Mock(MockBehavior.Strict); + mockISw360CreatorService = new Mock(MockBehavior.Strict); + mockISW360Service = new Mock(MockBehavior.Strict); } [TestCase] @@ -93,6 +105,49 @@ public void ValidateAppSettings_TestNegative() Assert.ThrowsAsync(() => CreatorValidator.ValidateAppSettings(CommonAppSettings, mockISw360ProjectService.Object, projectReleases)); } + [TestCase] + public async Task TriggerFossologyValidation_TestPositive() + { + // Arrange + var appSettings = new CommonAppSettings() + { + SW360 = new SW360() + { + URL = "https://sw360.example.com" + } + }; + var responseBody = "{\"_embedded\":{\"sw360:releases\":[{\"_links\":{\"self\":{\"href\":\"https://sw360.example.com/resource/api/releases/123\"}}}]}}"; + 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.GetReleases()).ReturnsAsync(responseBody); + mockISW360Service.Setup(x => x.GetReleaseDataOfComponent(It.IsAny())).ReturnsAsync(releasesInfo); + mockISw360CreatorService.Setup(x => x.TriggerFossologyProcessForValidation(It.IsAny(), It.IsAny())).ReturnsAsync(fossTriggerStatus); + mockISW360ApicommunicationFacade.Setup(x => x.GetReleaseById(It.IsAny())).ReturnsAsync(new HttpResponseMessage + { + Content = new StringContent("{\"Name\":\"TestRelease\",\"Version\":\"1.0\",\"ClearingState\":\"APPROVED\"}") + }); + mockISW360ApicommunicationFacade.Setup(x => x.TriggerFossologyProcess(It.IsAny(), It.IsAny())).ReturnsAsync(triggerStatusResponse); + // Act + await CreatorValidator.TriggerFossologyValidation(appSettings, mockISW360ApicommunicationFacade.Object); + // Assert + mockISW360ApicommunicationFacade.Verify(x => x.GetReleases(), Times.Once); + mockISW360ApicommunicationFacade.Verify(x => x.TriggerFossologyProcess(It.IsAny(), It.IsAny()), Times.Once); + } } } diff --git a/src/LCT.SW360PackageCreator/CreatorValidator.cs b/src/LCT.SW360PackageCreator/CreatorValidator.cs index 5168d967..4dad2d97 100644 --- a/src/LCT.SW360PackageCreator/CreatorValidator.cs +++ b/src/LCT.SW360PackageCreator/CreatorValidator.cs @@ -11,6 +11,14 @@ 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; namespace LCT.SW360PackageCreator @@ -21,6 +29,7 @@ namespace LCT.SW360PackageCreator public static class CreatorValidator { static readonly ILog Logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static IEnvironmentHelper environmentHelper; public static async Task ValidateAppSettings(CommonAppSettings appSettings, ISw360ProjectService sw360ProjectService, ProjectReleases projectReleases) { string sw360ProjectName = await sw360ProjectService.GetProjectNameByProjectIDFromSW360(appSettings.SW360.ProjectID, appSettings.SW360.ProjectName,projectReleases); @@ -41,5 +50,74 @@ public static async Task ValidateAppSettings(CommonAppSettings appSettings, } return 0; } + public static async Task TriggerFossologyValidation(CommonAppSettings appSettings, ISW360ApicommunicationFacade sW360ApicommunicationFacade) + { + IEnvironmentHelper environmentHelper = new EnvironmentHelper(); + ISW360CommonService sw360CommonService = new SW360CommonService(sW360ApicommunicationFacade); + ISw360CreatorService sw360CreatorService = new Sw360CreatorService(sW360ApicommunicationFacade, sw360CommonService); + ISW360Service sw360Service = new Sw360Service(sW360ApicommunicationFacade, sw360CommonService, environmentHelper); + ReleasesInfo releasesInfo = new ReleasesInfo(); + + try + { + string responseBody = await sW360ApicommunicationFacade.GetReleases(); + var modelMappedObject = JsonConvert.DeserializeObject(responseBody); + var releaseId = string.Empty; + if (modelMappedObject != null && modelMappedObject.Embedded?.Sw360Releases?.Count > 0) + { + foreach (var ReleaseidList in modelMappedObject.Embedded?.Sw360Releases) + { + var releaseUrl = ReleaseidList.Links?.Self?.Href; + releasesInfo = await CallApiAsync(releaseUrl, sw360Service); + if (releasesInfo != null) + { + releaseId = CommonHelper.GetSubstringOfLastOccurance(releaseUrl, "/"); + break; + } + } + } + else + { + Logger.Debug($"TriggerFossologyValidation():Trigger Fossology Process validation failed"); + Logger.Error($"Trigger Fossology Process validation failed"); + environmentHelper.CallEnvironmentExit(-1); + } + if (releasesInfo != null) + { + string sw360link = $"{releasesInfo.Name}:{releasesInfo.Version}:{appSettings.SW360.URL}{ApiConstant.Sw360ReleaseUrlApiSuffix}" + + $"{releaseId}#/tab-Summary"; + FossTriggerStatus fossResult = await sw360CreatorService.TriggerFossologyProcessForValidation(releaseId, sw360link); + if (!string.IsNullOrEmpty(fossResult?.Links?.Self?.Href)) + { + Logger.Logger.Log(null, Level.Info, $"SW360 Fossology Process validation successfull!!", null); + } + } + } + catch (AggregateException ex) + { + Logger.Debug($"\tError in TriggerFossologyProcess--{ex}"); + Logger.Error($"Trigger Fossology Process failed.Please check fossology configuration in sw360"); + environmentHelper.CallEnvironmentExit(-1); + } + } + private static async Task CallApiAsync(string endpoint, ISW360Service sw360Service) + { + try + { + ReleasesInfo releasesInfo = await sw360Service.GetReleaseDataOfComponent(endpoint); + var clearingState = releasesInfo.ClearingState?.ToString(); + if (clearingState == "APPROVED") + { + // Return the result if the clearingState is "approved" + return releasesInfo; + } + } + catch (Exception ex) + { + Logger.Debug($"CallApiAsync():{ex}"); + } + + return null; + } } } diff --git a/src/LCT.SW360PackageCreator/Program.cs b/src/LCT.SW360PackageCreator/Program.cs index 83c977db..ad44903e 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; @@ -88,6 +89,12 @@ 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) + { + if (await FossologyUrlValidation(appSettings)) + 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 +103,66 @@ static async Task Main(string[] args) PipelineArtifactUploader.UploadArtifacts(); } + public static async Task FossologyUrlValidation(CommonAppSettings appSettings) + { + string url = appSettings.SW360.Fossology.URL.ToLower(); + string prodFossUrl = "automation.fossology".ToLower(); + string stageFossUrl = "stage.fossology".ToLower(); + environmentHelper = new EnvironmentHelper(); + + if (string.IsNullOrEmpty(appSettings.SW360.Fossology.URL)) + { + Logger.Error($"Fossology URL is not provided ,Please make sure to add Fossologyurl in appsettings.."); + Logger.Debug($"Fossologyurlcheck() : 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 + using (HttpClient client = new HttpClient()) + { + 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($"Fossologyurlcheck() : 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($"Fossologyurlcheck() : Fossology URL is not valid.{ex}"); + environmentHelper.CallEnvironmentExit(-1); + } + } + } + else + { + Logger.Debug($"Fossologyurlcheck() : 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($"Fossologyurlcheck() : Fossology url not provided in appsettings"); + environmentHelper.CallEnvironmentExit(-1); + } + return false; + } 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..1b50bbb2 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..f07b6676 100644 --- a/src/SW360IntegrationTest/Alpine/ComponentCreatorInitialAlpine.cs +++ b/src/SW360IntegrationTest/Alpine/ComponentCreatorInitialAlpine.cs @@ -65,6 +65,7 @@ public void ComponentCreatorExe_ProvidedBOMFilePath_ReturnsSuccess() TestConstant.SW360ProjectID, testParameters.SW360ProjectID, TestConstant.SW360ProjectName, testParameters.SW360ProjectName, TestConstant.ProjectType,"ALPINE", + 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..8ca50c3f 100644 --- a/src/SW360IntegrationTest/Conan/ComponentCreatorInitialConan.cs +++ b/src/SW360IntegrationTest/Conan/ComponentCreatorInitialConan.cs @@ -55,6 +55,7 @@ public void TestComponentCreatorExe_Conan() TestConstant.SW360AuthTokenType, testParameters.SW360AuthTokenType, TestConstant.SW360ProjectID, testParameters.SW360ProjectID, TestConstant.SW360ProjectName, testParameters.SW360ProjectName, + TestConstant.FossologyURL, testParameters.FossUrl, 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..81264ed5 100644 --- a/src/SW360IntegrationTest/Debian/ComponentCreatorInitialDebian.cs +++ b/src/SW360IntegrationTest/Debian/ComponentCreatorInitialDebian.cs @@ -64,6 +64,7 @@ public void ComponentCreatorExe_ProvidedBOMFilePath_ReturnsSuccess() TestConstant.SW360ProjectID, testParameters.SW360ProjectID, TestConstant.SW360ProjectName, testParameters.SW360ProjectName, TestConstant.ProjectType,"DEBIAN", + TestConstant.FossologyURL, testParameters.FossUrl, 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..f4907ec4 100644 --- a/src/SW360IntegrationTest/Maven/ComponentCreatorInitialMaven.cs +++ b/src/SW360IntegrationTest/Maven/ComponentCreatorInitialMaven.cs @@ -65,6 +65,7 @@ public void ComponentCreatorExe_ProvidedBOMFilePath_ReturnsSuccess() TestConstant.SW360AuthTokenType, testParameters.SW360AuthTokenType, TestConstant.SW360ProjectID, testParameters.SW360ProjectID, TestConstant.SW360ProjectName, testParameters.SW360ProjectName, + TestConstant.FossologyURL, testParameters.FossUrl, TestConstant.Mode,""}), "Test to run Package Creator EXE execution"); } diff --git a/src/SW360IntegrationTest/NPM/ComponentCreatorTestMode.cs b/src/SW360IntegrationTest/NPM/ComponentCreatorTestMode.cs index 8c8cc5e7..f46ec99e 100644 --- a/src/SW360IntegrationTest/NPM/ComponentCreatorTestMode.cs +++ b/src/SW360IntegrationTest/NPM/ComponentCreatorTestMode.cs @@ -63,6 +63,7 @@ public void TestComponentCreatorExe_TestMode() TestConstant.SW360AuthTokenType, testParameters.SW360AuthTokenType, TestConstant.SW360ProjectID, testParameters.SW360ProjectID, TestConstant.SW360ProjectName, testParameters.SW360ProjectName, + TestConstant.FossologyURL, testParameters.FossUrl, 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..d62022f4 100644 --- a/src/SW360IntegrationTest/NPM/ComponentCreatorWithUpdatedComponents.cs +++ b/src/SW360IntegrationTest/NPM/ComponentCreatorWithUpdatedComponents.cs @@ -67,6 +67,7 @@ public void TestComponentCreatorExe() TestConstant.SW360AuthTokenType, testParameters.SW360AuthTokenType, TestConstant.SW360ProjectID, testParameters.SW360ProjectID, TestConstant.SW360ProjectName, testParameters.SW360ProjectName, + TestConstant.FossologyURL, testParameters.FossUrl, 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..7cb328ce 100644 --- a/src/SW360IntegrationTest/Nuget/ComponentCreatorInitialNuget.cs +++ b/src/SW360IntegrationTest/Nuget/ComponentCreatorInitialNuget.cs @@ -65,6 +65,7 @@ public void ComponentCreatorExe_ProvidedBOMFilePath_ReturnsSuccess() TestConstant.SW360ProjectID, testParameters.SW360ProjectID, TestConstant.SW360ProjectName, testParameters.SW360ProjectName, TestConstant.ProjectType,"NUGET", + TestConstant.FossologyURL, testParameters.FossUrl, 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..932a6f80 100644 --- a/src/SW360IntegrationTest/Nuget/NugetTemplate/ComponentCreatorNugetTemplate.cs +++ b/src/SW360IntegrationTest/Nuget/NugetTemplate/ComponentCreatorNugetTemplate.cs @@ -67,6 +67,7 @@ public void ComponentCreatorExe_ProvidedBOMFilePath_ReturnsSuccess() TestConstant.SW360ProjectID, testParameters.SW360ProjectID, TestConstant.SW360ProjectName, testParameters.SW360ProjectName, TestConstant.ProjectType,"NUGET", + TestConstant.FossologyURL, testParameters.FossUrl, TestConstant.Mode,""}); Assert.IsTrue(value == 0 || value == 2, diff --git a/src/SW360IntegrationTest/Python/ComponentCreatorInitialPython.cs b/src/SW360IntegrationTest/Python/ComponentCreatorInitialPython.cs index 088ea1e7..32051951 100644 --- a/src/SW360IntegrationTest/Python/ComponentCreatorInitialPython.cs +++ b/src/SW360IntegrationTest/Python/ComponentCreatorInitialPython.cs @@ -63,6 +63,7 @@ public void ComponentCreatorExe_ProvidedBOMFilePath_ReturnsSuccess() TestConstant.SW360AuthTokenType, testParameters.SW360AuthTokenType, TestConstant.SW360ProjectID, testParameters.SW360ProjectID, TestConstant.SW360ProjectName, testParameters.SW360ProjectName, + TestConstant.FossologyURL, testParameters.FossUrl, 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/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",