Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
143 changes: 0 additions & 143 deletions app_dart/lib/src/model/common/presubmit_completed_check.dart

This file was deleted.

45 changes: 32 additions & 13 deletions app_dart/lib/src/model/common/presubmit_guard_conclusion.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,56 +32,75 @@ enum PresubmitGuardConclusionResult {
internalError,
}

/// Represents the current state of jobs in a CI stage.
class PresubmitGuardState {
final int remaining;
final int failed;

const PresubmitGuardState({required this.remaining, required this.failed});

@override
bool operator ==(Object other) =>
identical(this, other) ||
(other is PresubmitGuardState &&
other.remaining == remaining &&
other.failed == failed);

@override
int get hashCode => Object.hash(remaining, failed);

@override
String toString() => 'PresubmitGuardState("$remaining", "$failed")';
}
Comment on lines +35 to +54

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could just be:

typedef PresubmitGuardState = ({int remaining, int failed});


/// Results from attempting to mark a staging task as completed.
///
/// See: [PresubmitGuard.markConclusion]
class PresubmitGuardConclusion {
final PresubmitGuardConclusionResult result;
final int remaining;
final PresubmitGuardState previousState;
final PresubmitGuardState currentState;
final String? checkRunGuard;
final int failed;
final String summary;
final String details;

const PresubmitGuardConclusion({
required this.result,
required this.remaining,
required this.previousState,
required this.currentState,
required this.checkRunGuard,
required this.failed,
required this.summary,
required this.details,
});

bool get isOk => result == PresubmitGuardConclusionResult.ok;

bool get isPending => isOk && remaining > 0;
bool get isPending => isOk && currentState.remaining > 0;

bool get isFailed => isOk && !isPending && failed > 0;

bool get isComplete => isOk && !isPending && !isFailed;
bool get isFailed => isOk && currentState.failed > 0;

@override
bool operator ==(Object other) =>
identical(this, other) ||
(other is PresubmitGuardConclusion &&
other.result == result &&
other.remaining == remaining &&
other.previousState == previousState &&
other.currentState == currentState &&
other.checkRunGuard == checkRunGuard &&
other.failed == failed &&
other.summary == summary &&
other.details == details);

@override
int get hashCode => Object.hashAll([
result,
remaining,
previousState,
currentState,
checkRunGuard,
failed,
summary,
details,
]);

@override
String toString() =>
'BuildConclusion("$result", "$remaining", "$failed", "$summary", "$details", "$checkRunGuard")';
'BuildConclusion("$result", "$previousState", "$currentState", "$summary", "$details", "$checkRunGuard")';
}
122 changes: 101 additions & 21 deletions app_dart/lib/src/model/common/presubmit_job_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,48 +2,128 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/// @docImport 'presubmit_job_state.dart';
library;

import 'package:buildbucket/buildbucket_pb.dart' as bbv2;
import 'package:buildbucket/buildbucket_pb.dart';
import 'package:cocoon_common/task_status.dart';
import 'package:fixnum/fixnum.dart';
import 'package:github/github.dart';
import 'package:meta/meta.dart';

import '../../foundation/utils.dart';
import '../../service/config.dart';
import '../../service/luci_build_service/build_tags.dart';
import '../../service/luci_build_service/user_data.dart';
import '../bbv2_extension.dart';
import '../firestore/base.dart';
import '../firestore/presubmit_guard.dart';
import '../github/checks.dart' as cocoon_checks;
import 'checks_extension.dart';

/// Represents the current state of a check run.
/// Unified representation of a completed presubmit job.
///
/// This class abstracts away the source of the job (GitHub CheckRun or BuildBucket Build)
/// to allow unified processing logic.
@immutable
class PresubmitJobState {
final String jobName;
final String name;
final String sha;
final RepositorySlug slug;
final TaskStatus status;
final int attemptNumber; //static int _currentAttempt(BuildTags buildTags)
final bool isMergeGroup;

final int checkRunId;
final int? checkSuiteId;
final String? headBranch;
final bool isUnifiedCheckRun;
final CiStage? stage;
final int? prNum;
final int attempt;
final int? startTime;
final int? endTime;
final String? summary;
final int? buildNumber;
final Int64? buildId;

const PresubmitJobState({
required this.jobName,
required this.name,
required this.sha,
required this.slug,
required this.status,
required this.attemptNumber,
required this.isMergeGroup,
required this.checkRunId,
required this.checkSuiteId,
required this.headBranch,
required this.isUnifiedCheckRun,
this.stage,
this.prNum,
this.attempt = 1,
this.startTime,
this.endTime,
this.summary,
this.buildNumber,
this.buildId,
});
}

extension BuildToPresubmitJobState on bbv2.Build {
PresubmitJobState toPresubmitJobState() => PresubmitJobState(
jobName: builder.builder,
status: status.toTaskStatus(),
attemptNumber: BuildTags.fromStringPairs(tags).currentAttempt,
startTime: startTime.toDateTime().millisecondsSinceEpoch,
endTime: endTime.toDateTime().millisecondsSinceEpoch,
summary: summaryMarkdown,
buildNumber: number,
buildId: id,
);
/// Creates a [PresubmitJobState] from a BuildBucket [Build].
factory PresubmitJobState.fromBuild(
Build build,
PresubmitUserData userData, {
TaskStatus? status,
}) {
return PresubmitJobState(
name: build.builder.builder,
sha: userData.commit.sha,
slug: userData.commit.slug,
status: status ?? build.status.toTaskStatus(),
isMergeGroup: _isMergeGroup(userData.commit.branch),
checkRunId: userData.guardCheckRunId ?? userData.checkRunId!,
checkSuiteId: userData.checkSuiteId,
headBranch: userData.commit.branch,
isUnifiedCheckRun: userData.guardCheckRunId != null,
stage: userData.stage,
prNum: userData.pullRequestNumber,
attempt: _getAttempt(build),
startTime: build.startTime.toDateTime().millisecondsSinceEpoch,
endTime: build.endTime.toDateTime().millisecondsSinceEpoch,
summary: build.summaryMarkdown,
buildNumber: build.number,
buildId: build.id,
);
}

static int _getAttempt(Build build) {
final tagSet = BuildTags.fromStringPairs(build.tags);
return tagSet.currentAttempt;
}

cocoon_checks.CheckRun get checkRun {
return cocoon_checks.CheckRun(
id: checkRunId,
name: isUnifiedCheckRun ? Config.kDashboardCheckName : name,
headSha: sha,
conclusion: status.toConclusion(),
checkSuite: CheckSuite(
id: checkSuiteId,
headBranch: headBranch,
headSha: sha,
conclusion: CheckRunConclusion.empty,
pullRequests: [],
),
);
}

PresubmitGuardId get guardId {
return PresubmitGuardId(
slug: slug,
prNum: prNum ?? 0,
checkRunId: checkRunId,
stage: stage ?? CiStage.fusionTests,
);
}

static bool _isMergeGroup(String? headBranch) {
if (headBranch == null) {
return false;
}
return tryParseGitHubMergeQueueBranch(headBranch).parsed;
}
}
Loading
Loading