public override SarifWorkItemModel Transform(SarifWorkItemModel workItemModel) { string newAreaPath = workItemModel.Context.GetProperty(NewAreaPath); workItemModel.Area = !string.IsNullOrEmpty(newAreaPath) ? newAreaPath : workItemModel.Area; return(workItemModel); }
public override SarifWorkItemModel Transform(SarifWorkItemModel workItemModel) { string newAreaPath = workItemModel.LocationUris?[0]?.OriginalString; workItemModel.Area = !string.IsNullOrEmpty(newAreaPath) ? newAreaPath : workItemModel.Area; return(workItemModel); }
public void WorkItemFilingContext_IncludeCustomBugFooter() { var context = new SarifWorkItemContext(); string customBugFooter = "This text is important to all my bugs."; context.AzureDevOpsDescriptionFooter = customBugFooter; var workItemModel = new SarifWorkItemModel(sarifLog: TestData.CreateSimpleLog(), context); workItemModel.BodyOrDescription.Should().Contain(customBugFooter); }
public void SarifWorkItemModel_PopulatesDescription() { var context = new SarifWorkItemContext(); SarifLog sarifLog = TestData.CreateOneIdThreeLocations(); var workItemModel = new SarifWorkItemModel(sarifLog, context); workItemModel.BodyOrDescription.Should().NotBeNullOrEmpty(); workItemModel.BodyOrDescription.Should().Contain(nameof(TestData.TestToolName)); workItemModel.BodyOrDescription.Should().Contain(sarifLog.Runs[0].VersionControlProvenance[0].RepositoryUri.OriginalString); workItemModel.BodyOrDescription.Should().Contain(WorkItemsResources.GeneralFooterText); workItemModel.BodyOrDescription.Should().NotContain(WorkItemsResources.AdoViewingOptions); }
public void WorkItemFilingContext_NullSarifLogRaisesArgumentNullException() { var areaPathTransformer = new AreaPathFromUri(); var context = new SarifWorkItemContext(); context.AddWorkItemModelTransformer(areaPathTransformer); context.Transformers[0].GetType().Should().Be(areaPathTransformer.GetType()); var workItemModel = new SarifWorkItemModel(sarifLog: TestData.CreateSimpleLog(), context); context.Transformers[0].Transform(workItemModel); workItemModel.Area.Should().BeNull(); }
public void SarifWorkItemModel_IncorporatesMultipleToolNamesIntoAdoDescription() { var context = new SarifWorkItemContext(); context.CurrentProvider = FilingClient.SourceControlProvider.AzureDevOps; SarifLog sarifLog = TestData.CreateTwoRunThreeResultLog(); var workItemModel = new SarifWorkItemModel(sarifLog, context); workItemModel.BodyOrDescription.Should().NotBeNullOrEmpty(); workItemModel.BodyOrDescription.Should().Contain(nameof(TestData.TestToolName)); workItemModel.BodyOrDescription.Should().Contain(nameof(TestData.SecondTestToolName)); workItemModel.BodyOrDescription.Should().Contain(TestData.FileLocations.Location1); }
public void SarifWorkItemModel_PopulatesAdoDescription() { // Context object specifies ADO as a filing client provider by default var context = new SarifWorkItemContext(); SarifLog sarifLog = TestData.CreateOneIdThreeLocations(); var workItemModel = new SarifWorkItemModel(sarifLog, context); workItemModel.BodyOrDescription.Should().NotBeNullOrEmpty(); workItemModel.BodyOrDescription.Should().Contain(nameof(TestData.TestToolName)); workItemModel.BodyOrDescription.Should().Contain(sarifLog.Runs[0].VersionControlProvenance[0].RepositoryUri.OriginalString); workItemModel.BodyOrDescription.Should().Contain(WorkItemsResources.AzureDevOpsDefaultDescriptionFooter); workItemModel.BodyOrDescription.Should().NotContain(WorkItemsResources.GitHubDefaultDescriptionFooter); }
public void SarifWorkItemModel_PopulatesAdoDescription() { var context = new SarifWorkItemContext(); context.CurrentProvider = FilingClient.SourceControlProvider.AzureDevOps; SarifLog sarifLog = TestData.CreateOneIdThreeLocations(); var workItemModel = new SarifWorkItemModel(sarifLog, context); workItemModel.BodyOrDescription.Should().NotBeNullOrEmpty(); workItemModel.BodyOrDescription.Should().Contain(nameof(TestData.TestToolName)); workItemModel.BodyOrDescription.Should().Contain(sarifLog.Runs[0].VersionControlProvenance[0].RepositoryUri.OriginalString); workItemModel.BodyOrDescription.Should().Contain(WorkItemsResources.ViewScansTabResults); }
public void WorkItemFilingContext_FetchUriSuccessfully() { var areaPathTransformer = new AreaPathFromUri(); var context = new SarifWorkItemContext(); context.AddWorkItemModelTransformer(areaPathTransformer); context.Transformers[0].GetType().Should().Be(areaPathTransformer.GetType()); SarifLog sarifLog = TestData.CreateOneIdThreeLocations(); var workItemModel = new SarifWorkItemModel(sarifLog, context); context.Transformers[0].Transform(workItemModel); workItemModel.Area.Should().Be(TestData.FileLocations.Location1); }
public virtual SarifLog FileWorkItems(SarifLog sarifLog) { using (Logger.BeginScopeContext(nameof(FileWorkItems))) { sarifLog = sarifLog ?? throw new ArgumentNullException(nameof(sarifLog)); sarifLog.SetProperty(LOGID_PROPERTY_NAME, Guid.NewGuid()); IReadOnlyList <SarifLog> logsToProcess = SplitLogFile(sarifLog); int logsToProcessCount = logsToProcess.Count; #if DEBUG if (!int.TryParse(Environment.GetEnvironmentVariable("SARIFTEST_FILINGLIMIT"), out logsToProcessCount)) { logsToProcessCount = logsToProcess.Count; } #endif Logger.LogInformation("Connecting to filing client: {accountOrOrganization}", this.FilingClient.AccountOrOrganization); this.FilingClient.Connect(this.FilingContext.PersonalAccessToken).Wait(); for (int splitFileIndex = 0; splitFileIndex < logsToProcessCount; splitFileIndex++) { SarifLog splitLog = logsToProcess[splitFileIndex]; SarifWorkItemModel sarifWorkItemModel = FileWorkItemInternal(splitLog, this.FilingContext, this.FilingClient); // IMPORTANT: as we update our partitioned logs, we are actually modifying the input log file // as well. That's because our partitioning is configured to reuse references to existing // run and result objects, even though they are partitioned into a separate log file. // This approach also us to update the original log file with the filed work item details // without requiring us to build a map of results between the original log and its // partioned log files. // if (sarifWorkItemModel != null) { UpdateLogWithWorkItemDetails(splitLog, sarifWorkItemModel.HtmlUri, sarifWorkItemModel.Uri); } } return(sarifLog); } }
public void WorkItemFilingContext_RoundTripsWorkItemModelTransformer() { var munger = new Munger(); var context = new SarifWorkItemContext(); context.AddWorkItemModelTransformer(munger); context.Transformers[0].GetType().Should().Be(munger.GetType()); context = RoundTripThroughXml(context); context.Transformers[0].GetType().Should().Be(munger.GetType()); string newAreaPath = Guid.NewGuid().ToString(); context.SetProperty(Munger.NewAreaPath, newAreaPath); var workItemModel = new SarifWorkItemModel(sarifLog: TestData.CreateSimpleLog(), context); context.Transformers[0].Transform(workItemModel); workItemModel.Area.Should().Be(newAreaPath); }
internal static void FileWorkItemsHelper(SarifLog sarifLog, SarifWorkItemContext filingContext, FilingClient filingClient) { // The helper below will initialize the sarif work item model with a copy // of the root pipeline filing context. This context will then be initialized // based on the current sarif log file that we're processing. SarifWorkItemModel workItemModel = new SarifWorkItemModel(sarifLog, filingContext); try { // Populate the work item with the target organization/repository information. // In ADO, certain fields (such as the area path) will defaut to the // project name and so this information is used in at least that context. workItemModel.RepositoryOrProject = filingClient.ProjectOrRepository; workItemModel.OwnerOrAccount = filingClient.AccountOrOrganization; foreach (SarifWorkItemModelTransformer transformer in workItemModel.Context.Transformers) { transformer.Transform(workItemModel); } filingClient.FileWorkItems(new[] { workItemModel }).Wait(); // TODO: We need to process updated work item models to persist filing // details back to the input SARIF file, if that was specified. // This code should either return or persist the updated models // via a property, so that the file work items command can do // this work. // // https://github.com/microsoft/sarif-sdk/issues/1774 } catch (Exception ex) { Console.Error.WriteLine(ex); } }
// TODO: make this async in the next iteration of the pipeline design // // public abstract SarifWorkItemModel Transform(SarifWorkItemModel workItemModel);
private void LogMetricsForProcessedModel(SarifLog sarifLog, SarifWorkItemModel sarifWorkItemModel, FilingResult filingResult, Dictionary <string, object> additionalCustomDimensions = null) { additionalCustomDimensions ??= new Dictionary <string, object>(); this.FilingResult = filingResult; string logGuid = sarifLog.GetProperty <Guid>("guid").ToString(); string tags = string.Join(",", sarifWorkItemModel.LabelsOrTags); string uris = sarifWorkItemModel.LocationUris?.Count > 0 ? string.Join(",", sarifWorkItemModel.LocationUris) : ""; var workItemMetrics = new Dictionary <string, object> { { "LogGuid", logGuid }, { "WorkItemModelGuid", sarifWorkItemModel.Guid }, { nameof(sarifWorkItemModel.Area), sarifWorkItemModel.Area }, { nameof(sarifWorkItemModel.BodyOrDescription), sarifWorkItemModel.BodyOrDescription }, { "FilingResult", filingResult.ToString() }, { nameof(sarifWorkItemModel.CommentOrDiscussion), sarifWorkItemModel.CommentOrDiscussion }, { nameof(sarifWorkItemModel.HtmlUri), sarifWorkItemModel.HtmlUri }, { nameof(sarifWorkItemModel.Iteration), sarifWorkItemModel.Iteration }, { "LabelsOrTags", tags }, { "LocationUri", uris }, { nameof(sarifWorkItemModel.Milestone), sarifWorkItemModel.Milestone }, { nameof(sarifWorkItemModel.OwnerOrAccount), sarifWorkItemModel.OwnerOrAccount }, { nameof(sarifWorkItemModel.RepositoryOrProject), sarifWorkItemModel.RepositoryOrProject }, { nameof(sarifWorkItemModel.Title), sarifWorkItemModel.Title }, { nameof(sarifWorkItemModel.Uri), sarifWorkItemModel.Uri }, }; foreach (string key in additionalCustomDimensions.Keys) { workItemMetrics.Add(key, additionalCustomDimensions[key]); } EventId coreEventId; switch (filingResult) { case FilingResult.Canceled: coreEventId = EventIds.WorkItemCanceledCoreMetrics; break; case FilingResult.ExceptionRaised: coreEventId = EventIds.WorkItemExceptionCoreMetrics; break; default: coreEventId = EventIds.WorkItemFiledCoreMetrics; break; } this.Logger.LogMetrics(coreEventId, workItemMetrics); Dictionary <string, RuleMetrics> ruleIdToMetricsMap = CreateRuleMetricsMap(sarifLog); foreach (string tool in ruleIdToMetricsMap.Keys) { RuleMetrics ruleMetrics = ruleIdToMetricsMap[tool]; var workItemDetailMetrics = new Dictionary <string, object> { { "LogGuid", logGuid }, { "WorkItemModelGuid", sarifWorkItemModel.Guid }, { nameof(ruleMetrics.Tool), ruleMetrics.Tool }, { nameof(ruleMetrics.RuleId), ruleMetrics.RuleId }, { nameof(ruleMetrics.ErrorCount), ruleMetrics.ErrorCount }, { nameof(ruleMetrics.WarningCount), ruleMetrics.WarningCount }, { nameof(ruleMetrics.NoteCount), ruleMetrics.NoteCount }, { nameof(ruleMetrics.OpenCount), ruleMetrics.OpenCount }, { nameof(ruleMetrics.ReviewCount), ruleMetrics.ReviewCount }, { nameof(ruleMetrics.SuppressedByTransformerCount), ruleMetrics.SuppressedByTransformerCount } }; this.Logger.LogMetrics(EventIds.WorkItemFiledDetailMetrics, workItemDetailMetrics); } }
public SarifWorkItemModel FileWorkItemInternal(SarifLog sarifLog, SarifWorkItemContext filingContext, FilingClient filingClient) { using (Logger.BeginScopeContext(nameof(FileWorkItemInternal))) { string logGuid = sarifLog.GetProperty <Guid>("guid").ToString(); // The helper below will initialize the sarif work item model with a copy // of the root pipeline filing context. This context will then be initialized // based on the current sarif log file that we're processing. // First intializes the contexts provider to the value in the current filing client. filingContext.CurrentProvider = filingClient.Provider; var sarifWorkItemModel = new SarifWorkItemModel(sarifLog, filingContext); try { // Populate the work item with the target organization/repository information. // In ADO, certain fields (such as the area path) will defaut to the // project name and so this information is used in at least that context. sarifWorkItemModel.OwnerOrAccount = filingClient.AccountOrOrganization; sarifWorkItemModel.RepositoryOrProject = filingClient.ProjectOrRepository; if (filingContext.SyncWorkItemMetadata) { Task <WorkItemModel> getMetadataTask = filingClient.GetWorkItemMetadata(sarifWorkItemModel); getMetadataTask.Wait(); sarifWorkItemModel = (SarifWorkItemModel)getMetadataTask.Result; } using (Logger.BeginScopeContext("RunTransformers")) { foreach (SarifWorkItemModelTransformer transformer in sarifWorkItemModel.Context.Transformers) { SarifWorkItemModel updatedSarifWorkItemModel = transformer.Transform(sarifWorkItemModel); // If a transformer has set the model to null, that indicates // it should be pulled from the work flow (i.e., not filed). if (updatedSarifWorkItemModel == null) { Dictionary <string, object> customDimentions = new Dictionary <string, object>(); customDimentions.Add("TransformerType", transformer.GetType().FullName); LogMetricsForProcessedModel(sarifLog, sarifWorkItemModel, FilingResult.Canceled, customDimentions); return(null); } sarifWorkItemModel = updatedSarifWorkItemModel; } } Task <IEnumerable <WorkItemModel> > task = filingClient.FileWorkItems(new[] { sarifWorkItemModel }); task.Wait(); this.FiledWorkItems.AddRange(task.Result); LogMetricsForProcessedModel(sarifLog, sarifWorkItemModel, FilingResult.Succeeded); } catch (Exception ex) { this.Logger.LogError(ex, "An exception was raised filing log '{logGuid}'.", logGuid); Dictionary <string, object> customDimentions = new Dictionary <string, object>(); customDimentions.Add("ExceptionType", ex.GetType().FullName); customDimentions.Add("ExceptionMessage", ex.Message); customDimentions.Add("ExceptionStackTrace", ex.ToString()); LogMetricsForProcessedModel(sarifLog, sarifWorkItemModel, FilingResult.ExceptionRaised, customDimentions); } return(sarifWorkItemModel); } }
private void FileWorkItemsHelper(SarifLog sarifLog, SarifWorkItemContext filingContext, FilingClient filingClient) { string logGuid = sarifLog.GetProperty<Guid>("guid").ToString(); // The helper below will initialize the sarif work item model with a copy // of the root pipeline filing context. This context will then be initialized // based on the current sarif log file that we're processing. // First intializes the contexts provider to the value in the current filing client. filingContext.CurrentProvider = filingClient.Provider; var sarifWorkItemModel = new SarifWorkItemModel(sarifLog, filingContext); try { // Populate the work item with the target organization/repository information. // In ADO, certain fields (such as the area path) will defaut to the // project name and so this information is used in at least that context. sarifWorkItemModel.OwnerOrAccount = filingClient.AccountOrOrganization; sarifWorkItemModel.RepositoryOrProject = filingClient.ProjectOrRepository; foreach (SarifWorkItemModelTransformer transformer in sarifWorkItemModel.Context.Transformers) { SarifWorkItemModel updatedSarifWorkItemModel = transformer.Transform(sarifWorkItemModel); // If a transformer has set the model to null, that indicates // it should be pulled from the work flow (i.e., not filed). if (updatedSarifWorkItemModel == null) { Dictionary<string, object> customDimentions = new Dictionary<string, object>(); customDimentions.Add("TransformerType", transformer.GetType().FullName); LogMetricsForProcessedModel(sarifLog, sarifWorkItemModel, FilingResult.Canceled, customDimentions); return; } sarifWorkItemModel = updatedSarifWorkItemModel; } Task<IEnumerable<WorkItemModel>> task = filingClient.FileWorkItems(new[] { sarifWorkItemModel }); task.Wait(); this.FiledWorkItems.AddRange(task.Result); // IMPORTANT: as we update our partitioned logs, we are actually modifying the input log file // as well. That's because our partitioning is configured to reuse references to existing // run and result objects, even though they are partitioned into a separate log file. // This approach also us to update the original log file with the filed work item details // without requiring us to build a map of results between the original log and its // partioned log files. // UpdateLogWithWorkItemDetails(sarifLog, sarifWorkItemModel.HtmlUri, sarifWorkItemModel.Uri); LogMetricsForProcessedModel(sarifLog, sarifWorkItemModel, FilingResult.Succeeded); } catch (Exception ex) { this.Logger.LogError(ex, "An exception was raised filing log '{logGuid}'.", logGuid); Dictionary<string, object> customDimentions = new Dictionary<string, object>(); customDimentions.Add("ExceptionType", ex.GetType().FullName); customDimentions.Add("ExceptionMessage", ex.Message); customDimentions.Add("ExceptionStackTrace", ex.ToString()); LogMetricsForProcessedModel(sarifLog, sarifWorkItemModel, FilingResult.ExceptionRaised, customDimentions); } }