コード例 #1
0
            public override SarifWorkItemModel Transform(SarifWorkItemModel workItemModel)
            {
                string newAreaPath = workItemModel.Context.GetProperty(NewAreaPath);

                workItemModel.Area = !string.IsNullOrEmpty(newAreaPath) ? newAreaPath : workItemModel.Area;

                return(workItemModel);
            }
コード例 #2
0
            public override SarifWorkItemModel Transform(SarifWorkItemModel workItemModel)
            {
                string newAreaPath = workItemModel.LocationUris?[0]?.OriginalString;

                workItemModel.Area = !string.IsNullOrEmpty(newAreaPath) ? newAreaPath : workItemModel.Area;

                return(workItemModel);
            }
コード例 #3
0
        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);
        }
コード例 #4
0
        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);
        }
コード例 #5
0
        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();
        }
コード例 #6
0
        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);
        }
コード例 #7
0
        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);
        }
コード例 #8
0
        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);
        }
コード例 #9
0
        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);
        }
コード例 #10
0
        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);
            }
        }
コード例 #11
0
        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);
        }
コード例 #12
0
        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);
            }
        }
コード例 #13
0
 // TODO: make this async in the next iteration of the pipeline design
 //
 //
 public abstract SarifWorkItemModel Transform(SarifWorkItemModel workItemModel);
コード例 #14
0
        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);
            }
        }
コード例 #15
0
        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);
            }
        }
コード例 #16
0
        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);
            }
        }