| // Copyright 2020 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import 'dart:core'; |
| import 'dart:io'; |
| |
| import 'package:github/github.dart' as github; |
| import 'package:github/hooks.dart'; |
| import 'package:retry/retry.dart'; |
| |
| import '../service/config.dart'; |
| import '../service/logging.dart'; |
| |
| /// Wrapper class for github checkrun service. This is used to simplify |
| /// mocking during testing because some of the subclasses are private. |
| class GithubChecksUtil { |
| const GithubChecksUtil(); |
| Future<Map<String, github.CheckRun>> allCheckRuns( |
| github.GitHub gitHubClient, |
| CheckSuiteEvent checkSuiteEvent, |
| ) async { |
| final List<github.CheckRun> allCheckRuns = await gitHubClient.checks.checkRuns |
| .listCheckRunsInSuite( |
| checkSuiteEvent.repository!.slug(), |
| checkSuiteId: checkSuiteEvent.checkSuite!.id!, |
| ) |
| .toList(); |
| return {for (github.CheckRun check in allCheckRuns) check.name as String: check}; |
| } |
| |
| Future<github.CheckSuite> getCheckSuite( |
| github.GitHub gitHubClient, |
| github.RepositorySlug slug, |
| int checkSuiteId, |
| ) async { |
| return gitHubClient.checks.checkSuites.getCheckSuite( |
| slug, |
| checkSuiteId: checkSuiteId, |
| ); |
| } |
| |
| /// Finds all check suites that are associated with a given git [ref]. |
| Future<List<github.CheckSuite>> listCheckSuitesForRef( |
| github.GitHub gitHubClient, |
| github.RepositorySlug slug, { |
| required String ref, |
| int? appId, |
| String? checkName, |
| }) async { |
| const RetryOptions r = RetryOptions( |
| maxAttempts: 3, |
| delayFactor: Duration(seconds: 2), |
| ); |
| return r.retry( |
| () async { |
| return gitHubClient.checks.checkSuites |
| .listCheckSuitesForRef( |
| slug, |
| ref: ref, |
| appId: appId, |
| checkName: checkName, |
| ) |
| .toList(); |
| }, |
| retryIf: (Exception e) => e is github.GitHubError || e is SocketException, |
| ); |
| } |
| |
| /// Sends a request to github checks api to update a [CheckRun] with a given |
| /// [status] and [conclusion]. |
| Future<void> updateCheckRun( |
| Config config, |
| github.RepositorySlug slug, |
| github.CheckRun checkRun, { |
| github.CheckRunStatus status = github.CheckRunStatus.queued, |
| github.CheckRunConclusion? conclusion, |
| String? detailsUrl, |
| github.CheckRunOutput? output, |
| }) async { |
| const RetryOptions r = RetryOptions( |
| maxAttempts: 3, |
| delayFactor: Duration(seconds: 2), |
| ); |
| return r.retry( |
| () async { |
| final github.GitHub gitHubClient = await config.createGitHubClient(slug: slug); |
| await gitHubClient.checks.checkRuns.updateCheckRun( |
| slug, |
| checkRun, |
| status: status, |
| conclusion: conclusion, |
| detailsUrl: detailsUrl, |
| output: output, |
| ); |
| }, |
| retryIf: (Exception e) => e is github.GitHubError || e is SocketException, |
| ); |
| } |
| |
| Future<github.CheckRun> getCheckRun( |
| Config config, |
| github.RepositorySlug slug, |
| int? id, |
| ) async { |
| const RetryOptions r = RetryOptions( |
| maxAttempts: 3, |
| delayFactor: Duration(seconds: 2), |
| ); |
| return r.retry( |
| () async { |
| final github.GitHub gitHubClient = await config.createGitHubClient(slug: slug); |
| return gitHubClient.checks.checkRuns.getCheckRun( |
| slug, |
| checkRunId: id!, |
| ); |
| }, |
| retryIf: (Exception e) => e is github.GitHubError || e is SocketException, |
| ); |
| } |
| |
| /// Sends a request to GitHub's Checks API to create a new [github.CheckRun]. |
| /// |
| /// The newly created checkrun will be associated in [slug] to [sha] as [name]. |
| /// |
| /// Optionally, will have [output] to give information to users. |
| Future<github.CheckRun> createCheckRun( |
| Config config, |
| github.RepositorySlug slug, |
| String sha, |
| String name, { |
| github.CheckRunOutput? output, |
| }) async { |
| const RetryOptions r = RetryOptions( |
| maxAttempts: 3, |
| delayFactor: Duration(seconds: 2), |
| ); |
| return r.retry( |
| () async { |
| return _createCheckRun( |
| config, |
| slug, |
| sha, |
| name, |
| output: output, |
| ); |
| }, |
| retryIf: (Exception e) => true, |
| onRetry: (Exception e) => log.warning( |
| 'createCheckRun fails for slug: ${slug.fullName}, sha: $sha, name: $name. Exception: ${e.toString()}', |
| ), |
| ); |
| } |
| |
| Future<github.CheckRun> _createCheckRun( |
| Config config, |
| github.RepositorySlug slug, |
| String sha, |
| String name, { |
| github.CheckRunOutput? output, |
| }) async { |
| final github.GitHub gitHubClient = await config.createGitHubClient(slug: slug); |
| return gitHubClient.checks.checkRuns.createCheckRun( |
| slug, |
| name: name, |
| headSha: sha, |
| output: output, |
| ); |
| } |
| } |