blob: 320e94a83ffb800fec5d89356aacf05e0f342270 [file] [log] [blame]
// Copyright 2025 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:cocoon_server/logging.dart';
import 'package:github/github.dart' as github;
import '../model/auto_submit_query_result.dart';
import 'validation.dart';
/// Validates that the base of the PR commit is not older than a specified in
/// configuration number of days.
class BaseCommitDateAllowed extends Validation {
BaseCommitDateAllowed({required super.config});
@override
String get name => 'BaseCommitDateAllowed';
@override
/// Implements the validation.
Future<ValidationResult> validate(
QueryResult result,
github.PullRequest messagePullRequest,
) async {
final slug = messagePullRequest.base!.repo!.slug();
final gitHubService = await config.createGithubService(slug);
final sha = messagePullRequest.base!.sha!;
final repositoryConfiguration = await config.getRepositoryConfiguration(
slug,
);
// If the base_commit_expiration is empty then the validation is turned off
// and the base commit creation date is ignored.
if (repositoryConfiguration.stalePrProtectionInDaysForBaseRefs.isEmpty) {
log.info('PR base commit creation date validation turned off');
return ValidationResult(
true,
Action.IGNORE_FAILURE,
'PR base commit creation date validation turned off',
);
}
// Check if PR base expiration validation is configured for this branch.
if (!repositoryConfiguration.stalePrProtectionInDaysForBaseRefs.containsKey(
'${slug.fullName}/${messagePullRequest.base!.ref}',
)) {
log.info(
'PR ${slug.fullName}/${messagePullRequest.number} is for branch: '
'${messagePullRequest.base!.ref} which does not match any configured PR '
'base for stale protection',
);
return ValidationResult(
true,
Action.IGNORE_FAILURE,
'The base commit expiration validation is not configured for this '
'branch.',
);
}
// If the base commit creation date is null then the validation fails but
// should not block the PR merging.
final commit = await gitHubService.getCommit(slug, sha);
if (commit.commit?.author?.date == null) {
log.info(
'PR ${slug.fullName}/${messagePullRequest.number} base commit creation '
'date is null.',
);
return ValidationResult(
false,
Action.IGNORE_FAILURE,
'Could not find the base commit creation date of the PR '
'${slug.fullName}/${messagePullRequest.number}.',
);
}
log.info(
'PR ${slug.fullName}/${messagePullRequest.number} requested for branch: '
'${messagePullRequest.base!.ref} with base creation date: '
'${commit.commit?.author?.date}.',
);
final isBaseRecent = commit.commit!.author!.date!.isAfter(
DateTime.now().subtract(
Duration(
days: repositoryConfiguration
.stalePrProtectionInDaysForBaseRefs['${slug.fullName}/${messagePullRequest.base!.ref}']!,
),
),
);
final message = isBaseRecent
? 'The base commit of the PR is recent enough for merging.'
: 'The base commit of the PR is older than '
'${repositoryConfiguration.stalePrProtectionInDaysForBaseRefs['${slug.fullName}/${messagePullRequest.base!.ref}']} '
'days and can not be merged. Please merge the latest changes '
'from the main into this branch and resubmit the PR.';
return ValidationResult(isBaseRecent, Action.REMOVE_LABEL, message);
}
}