public async Task GetsCheckRunWithRepositoryId() { using (var repoContext = await _github.CreateRepositoryContext(new NewRepository(Helper.MakeNameWithTimestamp("public-repo")) { AutoInit = true })) { // Create a new feature branch var headCommit = await _github.Repository.Commit.Get(repoContext.RepositoryId, "master"); var featureBranch = await Helper.CreateFeatureBranch(repoContext.RepositoryOwner, repoContext.RepositoryName, headCommit.Sha, "my-feature"); // Create a check run for the feature branch var newCheckRun = new NewCheckRun("name", featureBranch.Object.Sha) { Status = CheckStatus.InProgress }; var created = await _githubAppInstallation.Check.Run.Create(repoContext.RepositoryId, newCheckRun); // Get the check var checkRun = await _githubAppInstallation.Check.Run.Get(repoContext.RepositoryId, created.Id); // Check result Assert.Equal(featureBranch.Object.Sha, checkRun.HeadSha); Assert.Equal("name", checkRun.Name); Assert.Equal(CheckStatus.InProgress, checkRun.Status); } }
private async void Process_pull_requestAsync(JToken pull_request) { // todo: read comments from repo /org admins though for things like // "I approve this" and then approve the changes and then wait for // "merge squashed/rebased/commit" (if enabled on repository). // seems I cannot create a status yet??? var newCheckRun = new NewCheckRun("Misc/NEWS", pull_request["head"]["sha"].Value <string>()) { Status = CheckStatus.InProgress }; var check = await Program.client.Check.Run.Create(pull_request["base"]["repo"]["owner"].Value <string>(), pull_request["base"]["repo"]["name"].Value <string>(), newCheckRun); var _issue = await Program.client.Issue.Get(pull_request["base"]["repo"]["owner"].Value <string>(), pull_request["base"]["repo"]["name"].Value <string>(), Convert.ToInt32(pull_request["number"].Value <string>())); foreach (var label in _issue.Labels) { if (label.Name != "skip news") { var _newCheckRunOutput = new NewCheckRunOutput("Misc/NEWS", "'skip news' label found!"); var _checkRunUpdate = new CheckRunUpdate { Status = CheckStatus.Completed, Output = _newCheckRunOutput, Conclusion = CheckConclusion.Success }; _ = await Program.client.Check.Run.Update(pull_request["base"]["repo"]["owner"].Value <string>(), pull_request["base"]["repo"]["name"].Value <string>(), check.Id, _checkRunUpdate); return;// label.Name == "skip news"; } } var files = await Program.client.PullRequest.Files(pull_request["base"]["repo"]["owner"].Value <string>(), pull_request["base"]["repo"]["name"].Value <string>(), Convert.ToInt32(pull_request["number"].Value <string>())); foreach (var file in files) { if (file.FileName.StartsWith("Misc/NEWS")) { var _newCheckRunOutput = new NewCheckRunOutput("Misc/NEWS", "Misc/NEWS entry found!"); var _checkRunUpdate = new CheckRunUpdate { Status = CheckStatus.Completed, Output = _newCheckRunOutput, Conclusion = CheckConclusion.Success }; _ = await Program.client.Check.Run.Update(pull_request["base"]["repo"]["owner"].Value <string>(), pull_request["base"]["repo"]["name"].Value <string>(), check.Id, _checkRunUpdate); return; // !file[:filename].starts_with ? ("Misc/NEWS"); } } var newCheckRunOutput = new NewCheckRunOutput("Misc/NEWS", "Misc/NEWS entry not found and 'skip news' is not added!"); var checkRunUpdate = new CheckRunUpdate { Status = CheckStatus.Completed, Output = newCheckRunOutput, Conclusion = CheckConclusion.Failure }; _ = await Program.client.Check.Run.Update(pull_request["base"]["repo"]["owner"].Value <string>(), pull_request["base"]["repo"]["name"].Value <string>(), check.Id, checkRunUpdate); }
public async Task GetsAllAnnotationsWithRepositoryId() { using (var repoContext = await _github.CreateRepositoryContext(new NewRepository(Helper.MakeNameWithTimestamp("public-repo")) { AutoInit = true })) { // Create a new feature branch var headCommit = await _github.Repository.Commit.Get(repoContext.RepositoryId, "master"); var featureBranch = await Helper.CreateFeatureBranch(repoContext.RepositoryOwner, repoContext.RepositoryName, headCommit.Sha, "my-feature"); // Create a check run for the feature branch var newCheckRun = new NewCheckRun("name", featureBranch.Object.Sha) { Status = CheckStatus.InProgress, Output = new NewCheckRunOutput("title", "summary") { Annotations = new[] { new NewCheckRunAnnotation("file.txt", "blob", 1, 1, CheckWarningLevel.Warning, "this is a warning") } } }; var created = await _githubAppInstallation.Check.Run.Create(repoContext.RepositoryId, newCheckRun); // Get the annotations var annotations = await _githubAppInstallation.Check.Run.GetAllAnnotations(repoContext.RepositoryId, created.Id).ToList(); // Check result Assert.Equal(1, annotations.Count); Assert.Equal("this is a warning", annotations.First().Message); Assert.Equal(CheckWarningLevel.Warning, annotations.First().WarningLevel); } }
public async Task UpdatesCheckRun() { using (var repoContext = await _github.CreateRepositoryContext(new NewRepository(Helper.MakeNameWithTimestamp("public-repo")) { AutoInit = true })) { // Create a new feature branch var headCommit = await _github.Repository.Commit.Get(repoContext.RepositoryId, "master"); var featureBranch = await Helper.CreateFeatureBranch(repoContext.RepositoryOwner, repoContext.RepositoryName, headCommit.Sha, "my-feature"); // Create a check run for the feature branch var newCheckRun = new NewCheckRun("name", featureBranch.Object.Sha) { Status = CheckStatus.Queued }; var checkRun = await _githubAppInstallation.Check.Run.Create(repoContext.RepositoryOwner, repoContext.RepositoryName, newCheckRun); // Update the check run var update = new CheckRunUpdate("new-name") { Status = CheckStatus.InProgress }; var result = await _githubAppInstallation.Check.Run.Update(repoContext.RepositoryOwner, repoContext.RepositoryName, checkRun.Id, update); // Check result Assert.NotNull(result); Assert.Equal(featureBranch.Object.Sha, result.HeadSha); Assert.Equal("new-name", result.Name); Assert.Equal(CheckStatus.InProgress, result.Status); } }
/// <summary> /// Creates a new check run for a specific commit in a repository /// </summary> /// <remarks> /// See the <a href="https://developer.github.com/v3/checks/runs/#create-a-check-run">Check Runs API documentation</a> for more information. /// </remarks> /// <param name="owner">The owner of the repository</param> /// <param name="name">The name of the repository</param> /// <param name="newCheckRun">Details of the Check Run to create</param> public IObservable <CheckRun> Create(string owner, string name, NewCheckRun newCheckRun) { Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); Ensure.ArgumentNotNull(newCheckRun, nameof(newCheckRun)); return(_client.Create(owner, name, newCheckRun).ToObservable()); }
/// <summary> /// Create a NewCheckRun based on the result of the merge policy /// </summary> /// <param name="result">The evaluation of the merge policy</param> /// <param name="sha">Sha of the latest commit</param> /// <returns>The new check run</returns> private NewCheckRun CheckRunForAdd(MergePolicyEvaluationResult result, string sha) { var newCheckRun = new NewCheckRun($"{MergePolicyConstants.MaestroMergePolicyDisplayName} - {result.MergePolicyInfo.DisplayName}", sha); newCheckRun.ExternalId = CheckRunId(result, sha); UpdateCheckRun(newCheckRun, result); return(newCheckRun); }
/// <inheritdoc /> public async Task <long> CreateCheckRun(long repositoryId, NewCheckRun initializer, CancellationToken cancellationToken) { logger.LogTrace("Create check run for ref {0} on repository {1}", initializer.HeadSha, repositoryId); var client = await CreateInstallationClient(repositoryId, cancellationToken).ConfigureAwait(false); var checkRun = await client.Check.Run.Create(repositoryId, initializer).ConfigureAwait(false); return(checkRun.Id); }
public async Task EnsuresNonEmptyArguments() { var gitHubClient = Substitute.For <IGitHubClient>(); var client = new ObservableCheckRunsClient(gitHubClient); var newCheckRun = new NewCheckRun("status", "123abc") { Status = CheckStatus.Queued }; Assert.Throws <ArgumentException>(() => client.Create("", "repo", newCheckRun)); Assert.Throws <ArgumentException>(() => client.Create("fake", "", newCheckRun)); }
public async Task RequestsCorrectUrlWithRepositoryId() { var gitHubClient = Substitute.For <IGitHubClient>(); var client = new ObservableCheckRunsClient(gitHubClient); var newCheckRun = new NewCheckRun("status", "123abc") { Status = CheckStatus.Queued }; client.Create(1, newCheckRun); gitHubClient.Check.Run.Received().Create(1, newCheckRun); }
public async Task EnsuresNonEmptyArguments() { var connection = Substitute.For <IApiConnection>(); var client = new CheckRunsClient(connection); var newCheckRun = new NewCheckRun("status", "123abc") { Status = CheckStatus.Queued }; await Assert.ThrowsAsync <ArgumentException>(() => client.Create("", "repo", newCheckRun)); await Assert.ThrowsAsync <ArgumentException>(() => client.Create("fake", "", newCheckRun)); }
public async Task PassMergeAsync(MergeData data) { var client = await GetInstallationClientAsync(data.InstallationId); var pr = await client.PullRequest.Get(data.RepositoryOwner, data.RepositoryName, data.PullRequestNumber); var prHead = pr.Head; var checkRun = new NewCheckRun($"PublishingScheduler Auto-Merge", prHead.Ref); checkRun.Status = CheckStatus.Completed; checkRun.Conclusion = CheckConclusion.Success; checkRun.Output = new NewCheckRunOutput($"{data.MergeTime} UTC", $"An auto-merge is scheduled for {data.MergeTime} UTC."); await client.Check.Run.Create(data.RepositoryOwner, data.RepositoryName, checkRun); }
public async Task RequestsCorrectUrlWithRepositoryId() { var connection = Substitute.For <IApiConnection>(); var client = new CheckRunsClient(connection); var newCheckRun = new NewCheckRun("status", "123abc") { Status = CheckStatus.Queued }; await client.Create(1, newCheckRun); connection.Received().Post <CheckRun>( Arg.Is <Uri>(u => u.ToString() == "repositories/1/check-runs"), newCheckRun, "application/vnd.github.antiope-preview+json"); }
/// <inheritdoc/> protected override async Task <object> CallGitHubApi(DialogContext dc, Octokit.GitHubClient gitHubClient, CancellationToken cancellationToken = default(CancellationToken)) { if (Owner != null && Name != null && NewCheckRun != null) { var ownerValue = Owner.GetValue(dc.State); var nameValue = Name.GetValue(dc.State); var newCheckRunValue = NewCheckRun.GetValue(dc.State); return(await gitHubClient.Check.Run.Create(ownerValue, nameValue, newCheckRunValue).ConfigureAwait(false)); } if (RepositoryId != null && NewCheckRun != null) { var repositoryIdValue = RepositoryId.GetValue(dc.State); var newCheckRunValue = NewCheckRun.GetValue(dc.State); return(await gitHubClient.Check.Run.Create((Int64)repositoryIdValue, newCheckRunValue).ConfigureAwait(false)); } throw new ArgumentNullException("Required [newCheckRun] arguments missing for GitHubClient.Check.Run.Create"); }
/// <summary> /// Create some properties of a NewCheckRun /// </summary> /// <param name="newCheckRun">The NewCheckRun that needs to be created</param> /// <param name="result">The result of that new check run</param> private void UpdateCheckRun(NewCheckRun newCheckRun, MergePolicyEvaluationResult result) { var output = FormatOutput(result); newCheckRun.Output = output; newCheckRun.Status = CheckStatus.Completed; if (result.Status == MergePolicyEvaluationStatus.Pending) { newCheckRun.Status = CheckStatus.InProgress; } else if (result.Status == MergePolicyEvaluationStatus.Success) { newCheckRun.Conclusion = "success"; newCheckRun.CompletedAt = DateTime.Now; } else { newCheckRun.Conclusion = "failure"; newCheckRun.CompletedAt = DateTime.UtcNow; } }
public async Task GetsAllCheckRuns() { using (var repoContext = await _github.CreateRepositoryContext(new NewRepository(Helper.MakeNameWithTimestamp("public-repo")) { AutoInit = true })) { // Create a new feature branch var headCommit = await _github.Repository.Commit.Get(repoContext.RepositoryId, "master"); var featureBranch = await Helper.CreateFeatureBranch(repoContext.RepositoryOwner, repoContext.RepositoryName, headCommit.Sha, "my-feature"); // Create a check run for the feature branch var newCheckRun = new NewCheckRun("name", featureBranch.Object.Sha) { Status = CheckStatus.InProgress }; await _githubAppInstallation.Check.Run.Create(repoContext.RepositoryOwner, repoContext.RepositoryName, newCheckRun); // Get the check var request = new CheckRunRequest { CheckName = "name", Status = CheckStatusFilter.InProgress }; var checkRuns = await _githubAppInstallation.Check.Run.GetAllForReference(repoContext.RepositoryOwner, repoContext.RepositoryName, featureBranch.Object.Sha, request); // Check result Assert.NotEmpty(checkRuns.CheckRuns); foreach (var checkRun in checkRuns.CheckRuns) { Assert.Equal(featureBranch.Object.Sha, checkRun.HeadSha); Assert.Equal("name", checkRun.Name); Assert.Equal(CheckStatus.InProgress, checkRun.Status); } } }
/// <summary> /// Generates a icon diff for the specified <see cref="PullRequest"/> /// </summary> /// <param name="repositoryId">The <see cref="PullRequest.Base"/> <see cref="Repository.Id"/></param> /// <param name="pullRequestNumber">The <see cref="PullRequest.Number"/></param> /// <param name="installationId">The <see cref="InstallationId.Id"/></param> /// <param name="scope">The <see cref="IServiceScope"/> for the operation</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param> /// <returns>A <see cref="Task"/> representing the running operation</returns> async Task ScanPullRequestImpl(long repositoryId, int pullRequestNumber, long installationId, IServiceScope scope, CancellationToken cancellationToken) { long? checkRunId = null; PullRequest pullRequest = null; Task <IReadOnlyList <PullRequestFile> > allChangedFilesTask = null; var gitHubManager = scope.ServiceProvider.GetRequiredService <IGitHubManager>(); async Task RunCheck() { if (pullRequest == null) { pullRequest = await gitHubManager.GetPullRequest(repositoryId, installationId, pullRequestNumber, cancellationToken).ConfigureAwait(false); logger.LogTrace("Repository is {0}/{1}", pullRequest.Base.Repository.Owner.Login, pullRequest.Base.Repository.Name); logger.LogTrace("Pull Request: \"{0}\" by {1}", pullRequest.Title, pullRequest.User.Login); } if (allChangedFilesTask == null || allChangedFilesTask.IsFaulted) { allChangedFilesTask = gitHubManager.GetPullRequestChangedFiles(pullRequest, installationId, cancellationToken); } if (!checkRunId.HasValue) { var ncr = new NewCheckRun(String.Format(CultureInfo.InvariantCulture, "Diffs - Pull Request #{0}", pullRequest.Number), pullRequest.Head.Sha) { StartedAt = DateTimeOffset.Now, Status = CheckStatus.Queued }; checkRunId = await gitHubManager.CreateCheckRun(repositoryId, installationId, ncr, cancellationToken).ConfigureAwait(false); } var allChangedFiles = await allChangedFilesTask.ConfigureAwait(false); var changedDmis = allChangedFiles.Where(x => x.FileName.EndsWith(".dmi", StringComparison.InvariantCultureIgnoreCase)).ToList(); if (changedDmis.Count == 0) { logger.LogDebug("Pull request has no changed .dmis, exiting"); await gitHubManager.UpdateCheckRun(repositoryId, installationId, checkRunId.Value, new CheckRunUpdate { CompletedAt = DateTimeOffset.Now, Status = CheckStatus.Completed, Conclusion = CheckConclusion.Neutral, Output = new NewCheckRunOutput(stringLocalizer["No Modified Icons"], stringLocalizer["No modified .dmi files were detected in this pull request"]) }, cancellationToken).ConfigureAwait(false); return; } logger.LogTrace("Pull request has icon changes, creating check run"); await GenerateDiffs(pullRequest, installationId, checkRunId.Value, changedDmis, scope, cancellationToken).ConfigureAwait(false); }; try { try { for (var I = 0; I <= NotFoundRetryAttempts; ++I) { try { await RunCheck().ConfigureAwait(false); break; } catch (NotFoundException) { //chance for spurious github failures if (I == NotFoundRetryAttempts) { throw; } await Task.Delay(NotFoundRetryDelay, cancellationToken).ConfigureAwait(false); } } } catch (OperationCanceledException) { throw; } catch (Exception e) { if (!checkRunId.HasValue) { throw; } logger.LogDebug(e, "Error occurred. Attempting to post debug comment"); try { await gitHubManager.UpdateCheckRun(repositoryId, installationId, checkRunId.Value, new CheckRunUpdate { CompletedAt = DateTimeOffset.Now, Status = CheckStatus.Completed, Conclusion = CheckConclusion.Failure, Output = new NewCheckRunOutput(stringLocalizer["Error generating diffs!"], stringLocalizer["Exception details:\n\n```\n{0}\n```\n\nPlease report this [here]({1})", e.ToString(), IssueReportUrl]) }, default).ConfigureAwait(false); } catch (Exception innerException) { throw new AggregateException(innerException, e); } } } catch (OperationCanceledException) { logger.LogTrace("Operation cancelled"); if (!checkRunId.HasValue) { throw; } await gitHubManager.UpdateCheckRun(repositoryId, installationId, checkRunId.Value, new CheckRunUpdate { CompletedAt = DateTimeOffset.Now, Status = CheckStatus.Completed, Conclusion = CheckConclusion.Neutral, Output = new NewCheckRunOutput(stringLocalizer["Operation Cancelled"], stringLocalizer["The operation was cancelled on the server, most likely due to app shutdown. You may attempt re-running it."]) }, default).ConfigureAwait(false); } }
/// <inheritdoc /> public async Task <CheckRun> CreateCheckRunAsync(string owner, string repository, string sha, string checkRunName, string checkRunTitle, string checkRunSummary, bool checkRunIsSuccess, Annotation[] annotations, DateTimeOffset?startedAt, DateTimeOffset?completedAt) { if (owner == null) { throw new ArgumentNullException(nameof(owner)); } if (repository == null) { throw new ArgumentNullException(nameof(repository)); } if (sha == null) { throw new ArgumentNullException(nameof(sha)); } if (checkRunTitle == null) { throw new ArgumentNullException(nameof(checkRunTitle)); } if (checkRunSummary == null) { throw new ArgumentNullException(nameof(checkRunSummary)); } if ((annotations?.Length ?? 0) > 50) { throw new ArgumentException("Cannot create more than 50 annotations at a time"); } var gitHubClient = await _gitHubAppClientFactory.CreateAppClientForLoginAsync(_tokenGenerator, owner); var checkRunsClient = gitHubClient?.Check?.Run; if (checkRunsClient == null) { throw new InvalidOperationException("ICheckRunsClient is null"); } var newCheckRun = new NewCheckRun(checkRunName, sha) { Output = new NewCheckRunOutput(checkRunTitle, checkRunSummary) { Annotations = annotations? .Select(annotation => new NewCheckRunAnnotation(annotation.Filename, annotation.BlobHref, annotation.LineNumber, annotation.EndLine, GetCheckWarningLevel(annotation), annotation.Message)) .ToArray() }, Status = CheckStatus.Completed, StartedAt = startedAt, CompletedAt = completedAt, Conclusion = checkRunIsSuccess ? CheckConclusion.Success : CheckConclusion.Failure }; var checkRun = await checkRunsClient.Create(owner, repository, newCheckRun); return(new CheckRun { Id = checkRun.Id, Url = checkRun.HtmlUrl, }); }
/// <summary> /// Creates a new check run for a specific commit in a repository /// </summary> /// <remarks> /// See the <a href="https://developer.github.com/v3/checks/runs/#create-a-check-run">Check Runs API documentation</a> for more information. /// </remarks> /// <param name="repositoryId">The Id of the repository</param> /// <param name="newCheckRun">Details of the Check Run to create</param> public IObservable <CheckRun> Create(long repositoryId, NewCheckRun newCheckRun) { Ensure.ArgumentNotNull(newCheckRun, nameof(newCheckRun)); return(_client.Create(repositoryId, newCheckRun).ToObservable()); }
public async Task ScanPullRequest(long repositoryId, int pullRequestNumber, IJobCancellationToken jobCancellationToken) { using (logger.BeginScope("Scanning pull request #{0} for repository {1}", pullRequestNumber, repositoryId)) using (serviceProvider.CreateScope()) { var cancellationToken = jobCancellationToken.ShutdownToken; var gitHubManager = serviceProvider.GetRequiredService <IGitHubManager>(); var pullRequest = await gitHubManager.GetPullRequest(repositoryId, pullRequestNumber, cancellationToken).ConfigureAwait(false); logger.LogTrace("Repository is {0}/{1}", pullRequest.Base.Repository.Owner.Login, pullRequest.Base.Repository.Name); logger.LogTrace("Pull Request: \"{0}\" by {1}", pullRequest.Title, pullRequest.User.Login); var changedMapsTask = gitHubManager.GetPullRequestChangedFiles(pullRequest, cancellationToken); var requestIdentifier = String.Concat(pullRequest.Base.Repository.Owner.Login, pullRequest.Base.Repository.Name, pullRequest.Number); var ncr = new NewCheckRun { HeadSha = pullRequest.Head.Sha, Name = String.Format(CultureInfo.InvariantCulture, "Renderings - Pull Request #{0}", pullRequest.Number), StartedAt = DateTimeOffset.Now, Status = CheckStatus.Queued }; var checkRunId = await gitHubManager.CreateCheckRun(repositoryId, ncr, cancellationToken).ConfigureAwait(false); Task HandleCancel() => gitHubManager.UpdateCheckRun(repositoryId, checkRunId, new CheckRunUpdate { CompletedAt = DateTimeOffset.Now, Status = CheckStatus.Completed, Conclusion = CheckConclusion.Neutral, Output = new CheckRunOutput(stringLocalizer["Operation Cancelled"], stringLocalizer["The operation was cancelled on the server, most likely due to app shutdown. You may attempt re-running it."], null, null, null) }, default); try { for (var I = 0; !pullRequest.Mergeable.HasValue && I < 5; cancellationToken.ThrowIfCancellationRequested(), cancellationToken.ThrowIfCancellationRequested(), ++I) { if (I == 0) { logger.LogTrace("Null mergable state on pull request, refreshing for a maximum of 10s"); } await Task.Delay(1000 *I, cancellationToken).ConfigureAwait(false); pullRequest = await gitHubManager.GetPullRequest(pullRequest.Base.Repository.Id, pullRequest.Number, cancellationToken).ConfigureAwait(false);; } if (!pullRequest.Mergeable.HasValue || !pullRequest.Mergeable.Value) { logger.LogDebug("Pull request unmergeable, aborting scan"); await gitHubManager.UpdateCheckRun(repositoryId, checkRunId, new CheckRunUpdate { CompletedAt = DateTimeOffset.Now, Status = CheckStatus.Completed, Conclusion = CheckConclusion.Failure, Output = new CheckRunOutput(stringLocalizer["Merge Conflict"], stringLocalizer["Unable to render pull requests in an unmergeable state"], null, null, null) }, cancellationToken).ConfigureAwait(false); return; } var allChangedMaps = await changedMapsTask.ConfigureAwait(false); var changedDmms = allChangedMaps.Where(x => x.FileName.EndsWith(".dmm", StringComparison.InvariantCultureIgnoreCase)).Select(x => x.FileName).ToList(); if (changedDmms.Count == 0) { logger.LogDebug("Pull request has no changed maps, exiting"); await gitHubManager.UpdateCheckRun(repositoryId, checkRunId, new CheckRunUpdate { CompletedAt = DateTimeOffset.Now, Status = CheckStatus.Completed, Conclusion = CheckConclusion.Neutral, Output = new CheckRunOutput(stringLocalizer["No Modified Maps"], stringLocalizer["No modified .dmm files were detected in this pull request"], null, null, null) }, cancellationToken).ConfigureAwait(false); return; } logger.LogTrace("Pull request has map changes, creating check run"); await GenerateDiffs(pullRequest, checkRunId, changedDmms, cancellationToken).ConfigureAwait(false); } catch (OperationCanceledException) { logger.LogTrace("Operation cancelled"); await HandleCancel().ConfigureAwait(false); } catch (Exception e) { logger.LogDebug(e, "Error occurred. Attempting to post debug comment"); try { await gitHubManager.UpdateCheckRun(repositoryId, checkRunId, new CheckRunUpdate { CompletedAt = DateTimeOffset.Now, Status = CheckStatus.Completed, Conclusion = CheckConclusion.Failure, Output = new CheckRunOutput(stringLocalizer["Error rendering maps!"], stringLocalizer["Exception details:\n\n```\n{0}\n```\n\nPlease report this [here]({1})", e.ToString(), IssueReportUrl], null, null, null) }, default).ConfigureAwait(false); throw; } catch (OperationCanceledException) { logger.LogTrace("Operation cancelled"); await HandleCancel().ConfigureAwait(false); } catch (Exception innerException) { throw new AggregateException(innerException, e); } } } }
private static async Task TryCreateCheckRun(GitHubClient installationClient, long repositoryId, NewCheckRun checkRun, ILogger logger) { // Ignore check run failures for now. Check run permissions were added later, so users might not have granted permissions to add check runs. try { await installationClient.Check.Run.Create(repositoryId, checkRun); } catch (Exception e) { logger.LogWarning(e, $"Failed to create check run for repository {repositoryId}."); } }
/// <summary> /// Generates a icon diff for the specified <see cref="PullRequest"/> /// </summary> /// <param name="repositoryId">The <see cref="PullRequest.Base"/> <see cref="Repository.Id"/></param> /// <param name="pullRequestNumber">The <see cref="PullRequest.Number"/></param> /// <param name="installationId">The <see cref="InstallationId.Id"/></param> /// <param name="scope">The <see cref="IServiceScope"/> for the operation</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param> /// <returns>A <see cref="Task"/> representing the running operation</returns> async Task ScanPullRequestImpl(long repositoryId, int pullRequestNumber, long installationId, IServiceScope scope, CancellationToken cancellationToken) { var gitHubManager = scope.ServiceProvider.GetRequiredService <IGitHubManager>(); var pullRequest = await gitHubManager.GetPullRequest(repositoryId, installationId, pullRequestNumber, cancellationToken).ConfigureAwait(false); logger.LogTrace("Repository is {0}/{1}", pullRequest.Base.Repository.Owner.Login, pullRequest.Base.Repository.Name); logger.LogTrace("Pull Request: \"{0}\" by {1}", pullRequest.Title, pullRequest.User.Login); var allChangedFilesTask = gitHubManager.GetPullRequestChangedFiles(pullRequest, installationId, cancellationToken); var requestIdentifier = String.Concat(pullRequest.Base.Repository.Owner.Login, pullRequest.Base.Repository.Name, pullRequest.Number); var ncr = new NewCheckRun { HeadSha = pullRequest.Head.Sha, Name = String.Format(CultureInfo.InvariantCulture, "Diffs - Pull Request #{0}", pullRequest.Number), StartedAt = DateTimeOffset.Now, Status = CheckStatus.Queued }; var checkRunId = await gitHubManager.CreateCheckRun(repositoryId, installationId, ncr, cancellationToken).ConfigureAwait(false); Task HandleCancel() => gitHubManager.UpdateCheckRun(repositoryId, installationId, checkRunId, new CheckRunUpdate { CompletedAt = DateTimeOffset.Now, Status = CheckStatus.Completed, Conclusion = CheckConclusion.Neutral, Output = new CheckRunOutput(stringLocalizer["Operation Cancelled"], stringLocalizer["The operation was cancelled on the server, most likely due to app shutdown. You may attempt re-running it."], null, null, null) }, default); try { var allChangedFiles = await allChangedFilesTask.ConfigureAwait(false); var changedDmis = allChangedFiles.Where(x => x.FileName.EndsWith(".dmi", StringComparison.InvariantCultureIgnoreCase)).Select(x => x.FileName).ToList(); if (changedDmis.Count == 0) { logger.LogDebug("Pull request has no changed .dmis, exiting"); await gitHubManager.UpdateCheckRun(repositoryId, installationId, checkRunId, new CheckRunUpdate { CompletedAt = DateTimeOffset.Now, Status = CheckStatus.Completed, Conclusion = CheckConclusion.Neutral, Output = new CheckRunOutput(stringLocalizer["No Modified Icons"], stringLocalizer["No modified .dnu files were detected in this pull request"], null, null, null) }, cancellationToken).ConfigureAwait(false); return; } logger.LogTrace("Pull request has icon changes, creating check run"); await GenerateDiffs(pullRequest, installationId, checkRunId, changedDmis, scope, cancellationToken).ConfigureAwait(false); } catch (OperationCanceledException) { logger.LogTrace("Operation cancelled"); await HandleCancel().ConfigureAwait(false); } catch (Exception e) { logger.LogDebug(e, "Error occurred. Attempting to post debug comment"); try { await gitHubManager.UpdateCheckRun(repositoryId, installationId, checkRunId, new CheckRunUpdate { CompletedAt = DateTimeOffset.Now, Status = CheckStatus.Completed, Conclusion = CheckConclusion.Failure, Output = new CheckRunOutput(stringLocalizer["Error generating diffs!"], stringLocalizer["Exception details:\n\n```\n{0}\n```\n\nPlease report this [here]({1})", e.ToString(), IssueReportUrl], null, null, null) }, default).ConfigureAwait(false); throw; } catch (OperationCanceledException) { logger.LogTrace("Operation cancelled"); await HandleCancel().ConfigureAwait(false); } catch (Exception innerException) { throw new AggregateException(innerException, e); } } }
/// <summary> /// Creates a CheckRun in the GitHub Api. /// </summary> /// <param name="owner">The name of the repository owner.</param> /// <param name="repository">The name of the repository.</param> /// <param name="sha">The sha we are creating this CheckRun for.</param> /// <param name="createCheckRun"></param> /// <param name="annotations">Array of Annotations for the CheckRun.</param> /// <param name="name">The name of the CheckRun.</param> /// <param name="title">The title of the CheckRun.</param> /// <param name="summary">The summary of the CheckRun.</param> /// <param name="success">If the CheckRun is a success.</param> /// <param name="startedAt">The time when processing started</param> /// <param name="completedAt">The time when processing finished</param> /// <returns></returns> public async Task <CheckRun> CreateCheckRunAsync(string owner, string repository, string sha, CreateCheckRun createCheckRun, Annotation[] annotations) { try { if (owner == null) { throw new ArgumentNullException(nameof(owner)); } if (repository == null) { throw new ArgumentNullException(nameof(repository)); } if (sha == null) { throw new ArgumentNullException(nameof(sha)); } if ((annotations?.Length ?? 0) > 50) { throw new ArgumentException("Cannot create more than 50 annotations at a time"); } var gitHubClient = await _gitHubAppClientFactory.CreateAppClientForLoginAsync(_tokenGenerator, owner); var checkRunsClient = gitHubClient?.Check?.Run; if (checkRunsClient == null) { throw new InvalidOperationException("ICheckRunsClient is null"); } var newCheckRun = new NewCheckRun(createCheckRun.Name, sha) { Output = new NewCheckRunOutput(createCheckRun.Title, createCheckRun.Summary) { Text = createCheckRun.Text, Images = createCheckRun.Images?.Select(image => new NewCheckRunImage(image.Alt, image.ImageUrl) { Caption = image.Caption }).ToArray(), Annotations = annotations? .Select(CreateNewCheckRunAnnotation) .ToArray() }, Status = CheckStatus.Completed, StartedAt = createCheckRun.StartedAt, CompletedAt = createCheckRun.CompletedAt, Conclusion = createCheckRun.Conclusion.ToOctokit() }; var checkRun = await checkRunsClient.Create(owner, repository, newCheckRun); return(new CheckRun { Id = checkRun.Id, Url = checkRun.HtmlUrl }); } catch (Exception ex) { throw new GitHubAppModelException("Error creating CheckRun.", ex); } }
private async Task StartExecution() { IReadOnlyList <Installation> installations = await this.gitHubAppClient.GitHubApps.GetAllInstallationsForCurrent().ConfigureAwait(false); try { if (!this.IsGitHubInstallationClientValid()) { throw new InvalidOperationException("Error: gitHubInstallationClient is invalid."); } if (IsPullRequest) { ICheckSuitesClient checkSuiteClient = gitHubInstallationClient.Check.Suite; CheckSuitesResponse x = await checkSuiteClient.GetAllForReference(CurrentRepository.Id, CommitSha).ConfigureAwait(false); if (x.TotalCount > 0) { long checkSuiteId = x.CheckSuites.FirstOrDefault().Id; bool res = await checkSuiteClient.Rerequest(CurrentRepository.Id, checkSuiteId); } else { var newCheckSuite = new NewCheckSuite(CommitSha); try { CheckSuite suite = await checkSuiteClient.Create( CurrentRepository.Owner.Login, CurrentRepository.Name, newCheckSuite) .ConfigureAwait(false); } catch (Exception ex) { } } return; } ICheckRunsClient checkRunClient = gitHubInstallationClient.Check.Run; // Create a new heckRun in GitHub var newCheckRun = new NewCheckRun("ScanX", CommitSha) { Status = CheckStatus.Queued, }; CheckRun checkRun = await checkRunClient.Create( CurrentRepository.Owner.Login, CurrentRepository.Name, newCheckRun) .ConfigureAwait(false); // --- Downoad a ZIP --- byte[] buffer = await ScanHelper.DownloadRepoZip(gitHubInstallationClient, CurrentRepository.Id, CommitSha).ConfigureAwait(false); int size = buffer.Length; // Upload ZIP to a storage blob string blobName = $"{RequestId.ToString()}"; string blobUri = await ScanHelper.UploadBufferToStorage(buffer, blobName); // Update check's status to "in progress" CheckRunUpdate checkRunUpdate = new CheckRunUpdate { Status = CheckStatus.InProgress, Name = checkRun.Name }; checkRun = await checkRunClient.Update(CurrentRepository.Id, checkRun.Id, checkRunUpdate).ConfigureAwait(false); // --- Start a scan --- // Simulate sending of a message to a SB queue // Create worker notification message MalwareDeterminationRequest scanRequest = new MalwareDeterminationRequest(); scanRequest.ClientId = "GitHubScanX"; scanRequest.FileName = $"{RequestId.ToString()}.zip"; scanRequest.FileSizeInBytes = 1000; //dummy scanRequest.RequestId = RequestId; scanRequest.Uri = new Uri(blobUri); // Notify worker (aka put the notification message to a queue) ScanXMock mock = new ScanXMock(); await mock.SendScanRequest(scanRequest).ConfigureAwait(false); // --- Poll for a scan completion --- MalwareDeterminationResult scanResult; do { await Task.Delay(500).ConfigureAwait(false); if (await mock.TryGetResult(RequestId)) { scanResult = await mock.GetResult(RequestId).ConfigureAwait(false); break; } }while (true); //!!!! for POC only checkRunUpdate.Status = CheckStatus.Completed; checkRunUpdate.CompletedAt = DateTime.UtcNow; checkRunUpdate.Conclusion = scanResult.WorkStatus == WorkStatus.Clean ? CheckConclusion.Success : CheckConclusion.Failure; if (checkRunUpdate.Conclusion == CheckConclusion.Failure) { checkRunUpdate.Output = new NewCheckRunOutput( "Scan Report", $"GitScan detected {scanResult.ConfirmedMalwares.Count()} infected files. See details below."); checkRunUpdate.Output.Text = "| File Path| Malware Type| AV Engines|\n"; checkRunUpdate.Output.Text += "|:---|:---|:---|\n"; foreach (var entry in scanResult.ConfirmedMalwares) { checkRunUpdate.Output.Text += $"|{entry.FileName}|{entry.MalwareInfo}|{string.Join(",", entry.AvEngines.ToArray())}"; } } checkRun = await checkRunClient.Update(CurrentRepository.Id, checkRun.Id, checkRunUpdate).ConfigureAwait(false); } catch (Exception ex) { Console.WriteLine($"Exception: {ex.Message}"); } }