internal static async Task <BuildTestInfoCollection> ListBuildTestInfosAsync(this DotNetQueryUtil queryUtil, BuildSearchOptionSet optionSet, bool includeAllTests = false) { TestOutcome[]? outcomes = includeAllTests ? null : new[] { TestOutcome.Failed }; var list = new List <BuildTestInfo>(); foreach (var build in await queryUtil.ListBuildsAsync(optionSet).ConfigureAwait(false)) { try { var collection = await DotNetUtil.ListDotNetTestRunsAsync(queryUtil.Server, build, outcomes); var buildTestInfo = new BuildTestInfo(build, collection.SelectMany(x => x.TestCaseResults).ToList()); list.Add(buildTestInfo); } catch (Exception ex) { Console.WriteLine($"Cannot get test info for {build.Id} {DevOpsUtil.GetBuildUri(build)}"); Console.WriteLine(ex.Message); } } return(new BuildTestInfoCollection(new ReadOnlyCollection <BuildTestInfo>(list))); }
public void AddFlatError(Expression <Func <string> > resourceExpression, params object[] parm) { var err = new ParserError() { Message = DotNetUtil.Msg(resourceExpression, parm), ErrorPoint = TextBuffer.NotValidPtr }; AddError(err); }
public void AddException(Exception e, Expression <Func <string> > resourceExpression, params object[] parm) { string error = DotNetUtil.Msg(resourceExpression, parm); var err = new ParserError(); string s = _textBuffer.GetLineAndColumn(out err.Line, out err.Column); err.Message = error + " " + s; err.ErrorPoint = _textBuffer.PointerNextChar; err.Ex = e; AddError(err); }
public void AddBuildError(Expression <Func <string> > resourceExpression, CodeElement elem, params object[] parm) { string error = DotNetUtil.Msg(resourceExpression, parm); var err = new ParserError(); string s = string.Empty; if (elem != null) { err.ErrorPoint = elem.SubString.From; s = " " + _textBuffer.GetLineAndColumn(out err.Line, out err.Column, err.ErrorPoint); } err.Message = error + s; AddError(err); }
/// <summary>Add an error from parserElement.</summary> /// <param name="element"></param> /// <param name="errorPoint"></param> /// <param name="wordCount"></param> /// <param name="resourceExpression"></param> /// <param name="parm"></param> /// <returns>Always false.</returns> public bool AddSyntaxError(ParserElementBase element, int errorPoint, int wordCount, Expression <Func <string> > resourceExpression, params object[] parm) { string error = DotNetUtil.Msg(resourceExpression, parm.Insert(element.GetRule(element).Name)); // AddSyntaxError( element, errorPoint, wordCount, error); var err = new ParserError(); err.WordCount = 0; err.ErrorPoint = errorPoint; err.Error = error; string s = _textBuffer.GetLineAndColumn(out err.Line, out err.Column, errorPoint); err.Message = error + " " + s; AddError(err); return(false); }
internal static async Task <List <Build> > ListBuildsAsync(this DotNetQueryUtil queryUtil, BuildSearchOptionSet optionSet) { if (optionSet.BuildIds.Count > 0 && optionSet.Definitions.Count > 0) { OptionFailure("Cannot specify builds and definitions", optionSet); throw CreateBadOptionException(); } var searchCount = optionSet.SearchCount ?? BuildSearchOptionSet.DefaultSearchCount; var repository = optionSet.Repository; var branch = optionSet.Branch; var before = optionSet.Before; var after = optionSet.After; if (branch is object && !branch.StartsWith("refs")) { branch = $"refs/heads/{branch}"; } var builds = new List <Build>(); if (optionSet.BuildIds.Count > 0) { if (optionSet.Repository is object) { OptionFailure("Cannot specify builds and repository", optionSet); throw CreateBadOptionException(); } if (optionSet.Branch is object) { OptionFailure("Cannot specify builds and branch", optionSet); throw CreateBadOptionException(); } if (optionSet.SearchCount is object) { OptionFailure("Cannot specify builds and count", optionSet); throw CreateBadOptionException(); } foreach (var buildInfo in optionSet.BuildIds) { if (!TryGetBuildId(optionSet, buildInfo, out var buildProject, out var buildId)) { OptionFailure($"Cannot convert {buildInfo} to build id", optionSet); throw CreateBadOptionException(); } var build = await queryUtil.Server.GetBuildAsync(buildProject, buildId).ConfigureAwait(false); builds.Add(build); } } else { var(project, definitions) = GetProjectAndDefinitions(); var collection = await queryUtil.ListBuildsAsync( searchCount, project, definitions : definitions, repositoryId : repository, branch : branch, includePullRequests : optionSet.IncludePullRequests, before : optionSet.Before, after : optionSet.After); builds.AddRange(collection); } // Exclude out the builds that are complicating results foreach (var excludedBuildId in optionSet.ExcludedBuildIds) { builds = builds.Where(x => x.Id != excludedBuildId).ToList(); } return(builds); (string Project, int[] Definitions) GetProjectAndDefinitions() { if (optionSet.Definitions.Count == 0) { return(optionSet.Project ?? DotNetUtil.DefaultAzureProject, Array.Empty <int>()); } string?project = null; var list = new List <int>(); foreach (var definition in optionSet.Definitions) { if (!DotNetUtil.TryGetDefinitionId(definition, out var definitionProject, out var definitionId)) { OptionFailureDefinition(definition, optionSet); throw CreateBadOptionException(); } if (definitionProject is object) { if (project is null) { project = definitionProject; } else if (!StringComparer.OrdinalIgnoreCase.Equals(definitionProject, project)) { throw new InvalidOperationException($"Conflicting project names {project} and {definitionProject}"); } } list.Add(definitionId); } project ??= DotNetUtil.DefaultAzureProject; return(project, list.ToArray()); }
public async Task <string> GetStatusIssueTextAsync(IGitHubClient gitHubClient) { var header = new StringBuilder(); var body = new StringBuilder(); var footer = new StringBuilder(); header.AppendLine("## Overview"); header.AppendLine("Please use these queries to discover issues"); await BuildOne("Blocking CI", "blocking-clean-ci", DotNetUtil.GetDefinitionKeyFromFriendlyName("runtime")).ConfigureAwait(false); await BuildOne("Blocking Official Build", "blocking-official-build", DotNetUtil.GetDefinitionKeyFromFriendlyName("runtime-official")).ConfigureAwait(false); await BuildOne("Blocking CI Optional", "blocking-clean-ci-optional", DotNetUtil.GetDefinitionKeyFromFriendlyName("runtime")); await BuildOne("Blocking Outerloop", "blocking-outerloop", null); // Blank line to move past the table header.AppendLine(""); BuildFooter(); return(header.ToString() + body.ToString() + footer.ToString()); void BuildFooter() { footer.AppendLine(@"## Goals 1. A minimum 95% passing rate for the `runtime` pipeline ## Resources 1. [runtime pipeline analytics](https://dnceng.visualstudio.com/public/_build?definitionId=686&view=ms.vss-pipelineanalytics-web.new-build-definition-pipeline-analytics-view-cardmetrics)"); } async Task BuildOne(string title, string label, DefinitionKey?definitionKey) { header.AppendLine($"- [{title}](https://github.com/dotnet/runtime/issues?q=is%3Aopen+is%3Aissue+label%3A{label})"); body.AppendLine($"## {title}"); body.AppendLine("|Status|Issue|Build Count|"); body.AppendLine("|---|---|---|"); var query = (await DoSearchAsync(gitHubClient, label).ConfigureAwait(false)) .OrderByDescending(x => x.Count); foreach (var(issue, count) in query) { var emoji = issue.Labels.Any(x => x.Name == "intermittent") ? ":warning:" : ":fire:"; var titleLimit = 75; var issueText = issue.Title.Length >= titleLimit ? issue.Title.Substring(0, titleLimit - 5) + " ..." : issue.Title; var issueEntry = $"[{issueText}]({issue.HtmlUrl})"; var countStr = count.HasValue ? count.ToString() : "N/A"; body.AppendLine($"|{emoji}|{issueEntry}|{countStr}|"); } } async Task <List <(Octokit.Issue Issue, int?Count)> > DoSearchAsync(IGitHubClient gitHubClient, string label) { var request = new SearchIssuesRequest() { Labels = new [] { label }, State = ItemState.Open, Type = IssueTypeQualifier.Issue, Repos = { { "dotnet", "runtime" } }, }; var result = await gitHubClient.Search.SearchIssues(request).ConfigureAwait(false); var list = new List <(Octokit.Issue Issue, int?Count)>(); foreach (var issue in result.Items) { var count = await GetImpactedBuildsCountAsync(issue.GetIssueKey()).ConfigureAwait(false); list.Add((issue, count)); } return(list); } async Task <int?> GetImpactedBuildsCountAsync(GitHubIssueKey issueKey) { var modelTrackingIssue = await TriageContextUtil .GetModelTrackingIssuesQuery(issueKey) .FirstOrDefaultAsync() .ConfigureAwait(false); if (modelTrackingIssue is null) { return(null); } var count = await Context .ModelTrackingIssueResults .Where(x => x.IsPresent && x.ModelTrackingIssueId == modelTrackingIssue.Id) .CountAsync() .ConfigureAwait(false); return(count);; } }
public static string BuildMsg(int line, int col, Expression <Func <string> > resourceExpression, params object[] parm) { string pos = (line > 0) ? " " + string.Format(MessageRes.LineAndCol, line, col) : string.Empty; return(DotNetUtil.Msg(resourceExpression, parm) + pos); }
/// <summary>Raise PropertyChanged when a property is changed.</summary> /// <param name="exp">Lambda expression. Feks ()=>PropertyName.</param> protected void RaisePropertyChanged(Expression <Func <object> > exp) { RaisePropertyChanged(DotNetUtil.GetMemberName(exp)); }
public async Task UpdateStatusIssue() { var header = new StringBuilder(); var body = new StringBuilder(); var footer = new StringBuilder(); header.AppendLine("## Overview"); header.AppendLine("Please use this queries to discover issues"); await BuildOne("Blocking CI", "blocking-clean-ci", DotNetUtil.GetBuildDefinitionKeyFromFriendlyName("runtime")); await BuildOne("Blocking Official Build", "blocking-official-build", DotNetUtil.GetBuildDefinitionKeyFromFriendlyName("runtime-official")); await BuildOne("Blocking CI Optional", "blocking-clean-ci-optional", DotNetUtil.GetBuildDefinitionKeyFromFriendlyName("runtime")); await BuildOne("Blocking Outerloop", "blocking-outerloop", null); // Blank line to move past the table header.AppendLine(""); BuildFooter(); await UpdateIssue(); void BuildFooter() { footer.AppendLine(@"## Goals 1. A minimum 95% passing rate for the `runtime` pipeline ## Resources 1. [runtime pipeline analytics](https://dnceng.visualstudio.com/public/_build?definitionId=686&view=ms.vss-pipelineanalytics-web.new-build-definition-pipeline-analytics-view-cardmetrics)"); } async Task BuildOne(string title, string label, BuildDefinitionKey?definitionKey) { header.AppendLine($"- [{title}](https://github.com/dotnet/runtime/issues?q=is%3Aopen+is%3Aissue+label%3A{label})"); body.AppendLine($"## {title}"); body.AppendLine("|Status|Issue|Build Count|"); body.AppendLine("|---|---|---|"); var query = (await DoSearch(label)) .Select(x => { var issueKey = x.GetIssueKey(); var count = definitionKey.HasValue ? GetImpactedBuildsCount(issueKey, definitionKey.Value) : null; return(x, Count: count); }) .OrderByDescending(x => x.Count); foreach (var(issue, count) in query) { var emoji = issue.Labels.Any(x => x.Name == "intermittent") ? ":warning:" : ":fire:"; var titleLimit = 75; var issueText = issue.Title.Length >= titleLimit ? issue.Title.Substring(0, titleLimit - 5) + " ..." : issue.Title; var issueEntry = $"[{issueText}]({issue.HtmlUrl})"; var countStr = count.HasValue ? count.ToString() : "N/A"; body.AppendLine($"|{emoji}|{issueEntry}|{countStr}|"); } } async Task <List <Octokit.Issue> > DoSearch(string label) { var request = new SearchIssuesRequest() { Labels = new [] { label }, State = ItemState.Open, Type = IssueTypeQualifier.Issue, Repos = { { "dotnet", "runtime" } }, }; var result = await GitHubClient.Search.SearchIssues(request); return(result.Items.ToList()); } async Task UpdateIssue() { var issueKey = new GitHubIssueKey("dotnet", "runtime", 702); var issueClient = GitHubClient.Issue; var issue = await issueClient.Get(issueKey.Organization, issueKey.Repository, issueKey.Number); var updateIssue = issue.ToUpdate(); updateIssue.Body = header.ToString() + body.ToString() + footer.ToString(); await GitHubClient.Issue.Update(issueKey.Organization, issueKey.Repository, issueKey.Number, updateIssue); } int?GetImpactedBuildsCount(GitHubIssueKey issueKey, BuildDefinitionKey definitionKey) { if (!TriageContextUtil.TryGetTimelineQuery(issueKey, out var timelineQuery)) { return(null); } // TODO: need to be able to filter to the repo the build ran against var count = Context.ModelTimelineItems .Include(x => x.ModelBuild) .ThenInclude(x => x.ModelBuildDefinition) .Where(x => x.ModelTimelineQueryId == timelineQuery.Id && x.ModelBuild.ModelBuildDefinition.AzureOrganization == definitionKey.Organization && x.ModelBuild.ModelBuildDefinition.AzureProject == definitionKey.Project && x.ModelBuild.ModelBuildDefinition.DefinitionId == definitionKey.Id) .Count(); return(count);; } }