| // Copyright 2019 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 'package:flutter/foundation.dart'; |
| |
| import '../model/commit.pb.dart'; |
| import '../model/task.pb.dart'; |
| |
| /// [Task.stageName] that maps to StageName enums. |
| // TODO(chillers): Remove these and use StageName enum when available. https://github.com/flutter/cocoon/issues/441 |
| class StageName { |
| static const String cirrus = 'cirrus'; |
| static const String cocoon = 'cocoon'; |
| static const String legacyLuci = 'chromebot'; |
| static const String luci = 'luci'; |
| static const String googleTest = 'google_internal'; |
| } |
| |
| /// Base URLs for various endpoints that can relate to a [Task]. |
| const String _cirrusUrl = 'https://cirrus-ci.com/github/flutter/flutter'; |
| const String _cirrusLogUrl = 'https://cirrus-ci.com/build/flutter/flutter'; |
| const String _luciUrl = 'https://ci.chromium.org/p/flutter'; |
| const String _googleTestUrl = 'https://flutter-rob.corp.google.com'; |
| |
| @immutable |
| class QualifiedTask { |
| const QualifiedTask({this.stage, this.task, this.pool}); |
| |
| QualifiedTask.fromTask(Task task) |
| : stage = task.stageName, |
| task = task.builderName, |
| pool = task.isFlaky ? 'luci.flutter.staging' : 'luci.flutter.prod'; |
| |
| final String? pool; |
| final String? stage; |
| final String? task; |
| |
| /// Get the URL for the configuration of this task. |
| /// |
| /// Luci tasks are stored on Luci. |
| /// Cirrus tasks are stored on Cirrus. |
| String get sourceConfigurationUrl { |
| assert(isLuci || isCirrus || isGoogleTest); |
| if (isCirrus) { |
| return '$_cirrusUrl/master'; |
| } else if (isLuci) { |
| return '$_luciUrl/builders/$pool/$task'; |
| } else if (isGoogleTest) { |
| return _googleTestUrl; |
| } |
| throw Exception('Failed to get source configuration url for $stage.'); |
| } |
| |
| /// Whether this task was run on google test. |
| bool get isGoogleTest => stage == StageName.googleTest; |
| |
| /// Whether this task was run on Cirrus CI. |
| bool get isCirrus => stage == StageName.cirrus; |
| |
| /// Whether the task was run on the LUCI infrastructre. |
| bool get isLuci => stage == StageName.cocoon || stage == StageName.legacyLuci || stage == StageName.luci; |
| |
| @override |
| bool operator ==(Object other) { |
| if (other.runtimeType != runtimeType) { |
| return false; |
| } |
| |
| if (isLuci) { |
| return other is QualifiedTask && other.task == task; |
| } |
| |
| return other is QualifiedTask && other.stage == stage && other.task == task; |
| } |
| |
| @override |
| int get hashCode { |
| // Ensure tasks from Cocoon or LUCI share the same columns. |
| if (isLuci) { |
| return StageName.cocoon.hashCode ^ task.hashCode; |
| } |
| |
| return stage.hashCode ^ task.hashCode; |
| } |
| } |
| |
| /// Get the URL for [Task] to view its log. |
| /// |
| /// Cirrus logs are located via their [Commit.sha]. |
| /// Otherwise, we can redirect to the LUCI build page for [Task]. |
| String logUrl(Task task, {Commit? commit}) { |
| if (task.stageName == StageName.cirrus) { |
| if (commit != null) { |
| return '$_cirrusLogUrl/${commit.sha}?branch=${commit.branch}'; |
| } else { |
| return '$_cirrusUrl/master'; |
| } |
| } |
| return QualifiedTask.fromTask(task).sourceConfigurationUrl; |
| } |