mirror of
https://github.com/flutter/packages.git
synced 2025-06-08 04:18:49 +08:00
[tool] Switch PR description overrides over to labels (#6145)
This commit is contained in:
@ -123,47 +123,49 @@ class VersionCheckCommand extends PackageLoopingCommand {
|
||||
'(e.g., PR description or commit message).\n\n'
|
||||
'If supplied, this is used to allow overrides to some version '
|
||||
'checks.');
|
||||
argParser.addOption(_prLabelsArg,
|
||||
help: 'A comma-separated list of labels associated with this PR, '
|
||||
'if applicable.\n\n'
|
||||
'If supplied, this may be to allow overrides to some version '
|
||||
'checks.');
|
||||
argParser.addFlag(_checkForMissingChanges,
|
||||
help: 'Validates that changes to packages include CHANGELOG and '
|
||||
'version changes unless they meet an established exemption.\n\n'
|
||||
'If used with --$_changeDescriptionFile, this is should only be '
|
||||
'used in pre-submit CI checks, to prevent the possibility of '
|
||||
'post-submit breakage if an override justification is not '
|
||||
'transferred into the commit message.',
|
||||
'If used with --$_prLabelsArg, this is should only be '
|
||||
'used in pre-submit CI checks, to prevent post-submit breakage '
|
||||
'when labels are no longer applicable.',
|
||||
hide: true);
|
||||
argParser.addFlag(_ignorePlatformInterfaceBreaks,
|
||||
help: 'Bypasses the check that platform interfaces do not contain '
|
||||
'breaking changes.\n\n'
|
||||
'This is only intended for use in post-submit CI checks, to '
|
||||
'prevent the possibility of post-submit breakage if a change '
|
||||
'description justification is not transferred into the commit '
|
||||
'message. Pre-submit checks should always use '
|
||||
'--$_changeDescriptionFile instead.',
|
||||
'prevent post-submit breakage when overriding the check with '
|
||||
'labels. Pre-submit checks should always use '
|
||||
'--$_prLabelsArg instead.',
|
||||
hide: true);
|
||||
}
|
||||
|
||||
static const String _againstPubFlag = 'against-pub';
|
||||
static const String _changeDescriptionFile = 'change-description-file';
|
||||
static const String _prLabelsArg = 'pr-labels';
|
||||
static const String _checkForMissingChanges = 'check-for-missing-changes';
|
||||
static const String _ignorePlatformInterfaceBreaks =
|
||||
'ignore-platform-interface-breaks';
|
||||
|
||||
/// The string that must be in [_changeDescriptionFile] to allow a breaking
|
||||
/// The label that must be on a PR to allow a breaking
|
||||
/// change to a platform interface.
|
||||
static const String _breakingChangeJustificationMarker =
|
||||
'## Breaking change justification';
|
||||
static const String _breakingChangeOverrideLabel =
|
||||
'override: allow breaking change';
|
||||
|
||||
/// The string that must be at the start of a line in [_changeDescriptionFile]
|
||||
/// to allow skipping a version change for a PR that would normally require
|
||||
/// one.
|
||||
static const String _missingVersionChangeJustificationMarker =
|
||||
'No version change:';
|
||||
/// The label that must be on a PR to allow skipping a version change for a PR
|
||||
/// that would normally require one.
|
||||
static const String _missingVersionChangeOverrideLabel =
|
||||
'override: no versioning needed';
|
||||
|
||||
/// The string that must be at the start of a line in [_changeDescriptionFile]
|
||||
/// to allow skipping a CHANGELOG change for a PR that would normally require
|
||||
/// one.
|
||||
static const String _missingChangelogChangeJustificationMarker =
|
||||
'No CHANGELOG change:';
|
||||
/// The label that must be on a PR to allow skipping a CHANGELOG change for a
|
||||
/// PR that would normally require one.
|
||||
static const String _missingChangelogChangeOverrideLabel =
|
||||
'override: no changelog needed';
|
||||
|
||||
final PubVersionFinder _pubVersionFinder;
|
||||
|
||||
@ -172,6 +174,7 @@ class VersionCheckCommand extends PackageLoopingCommand {
|
||||
late final List<String> _changedFiles;
|
||||
|
||||
late final String _changeDescription = _loadChangeDescription();
|
||||
late final Set<String> _prLabels = _getPRLabels();
|
||||
|
||||
@override
|
||||
final String name = 'version-check';
|
||||
@ -498,18 +501,25 @@ ${indentation}The first version listed in CHANGELOG.md is $fromChangeLog.
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_getChangeDescription().contains(_breakingChangeJustificationMarker)) {
|
||||
if (_prLabels.contains(_breakingChangeOverrideLabel)) {
|
||||
logWarning(
|
||||
'${indentation}Allowing breaking change to ${package.displayName} '
|
||||
'due to "$_breakingChangeJustificationMarker" in the change '
|
||||
'description.');
|
||||
'due to the "$_breakingChangeOverrideLabel" label.');
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
String _getChangeDescription() => _changeDescription;
|
||||
/// Returns the labels associated with this PR, if any, or an empty set
|
||||
/// if that flag is not provided.
|
||||
Set<String> _getPRLabels() {
|
||||
final String labels = getStringArg(_prLabelsArg);
|
||||
if (labels.isEmpty) {
|
||||
return <String>{};
|
||||
}
|
||||
return labels.split(',').map((String label) => label.trim()).toSet();
|
||||
}
|
||||
|
||||
/// Returns the contents of the file pointed to by [_changeDescriptionFile],
|
||||
/// or an empty string if that flag is not provided.
|
||||
@ -569,44 +579,38 @@ ${indentation}The first version listed in CHANGELOG.md is $fromChangeLog.
|
||||
}
|
||||
|
||||
if (state.needsVersionChange) {
|
||||
final String changeDescription = _getChangeDescription();
|
||||
if (changeDescription.split('\n').any((String line) =>
|
||||
line.startsWith(_missingVersionChangeJustificationMarker))) {
|
||||
logWarning('Ignoring lack of version change due to '
|
||||
'"$_missingVersionChangeJustificationMarker" in the '
|
||||
'change description.');
|
||||
} else if (_isAllowedDependabotChange(package, changeDescription)) {
|
||||
if (_prLabels.contains(_missingVersionChangeOverrideLabel)) {
|
||||
logWarning('Ignoring lack of version change due to the '
|
||||
'"$_missingVersionChangeOverrideLabel" label.');
|
||||
} else if (_isAllowedDependabotChange(package, _changeDescription)) {
|
||||
logWarning('Ignoring lack of version change for Dependabot change to '
|
||||
'a known internal dependency.');
|
||||
} else {
|
||||
printError(
|
||||
'No version change found, but the change to this package could '
|
||||
'not be verified to be exempt from version changes according to '
|
||||
'repository policy. If this is a false positive, please '
|
||||
'add a line starting with\n'
|
||||
'$_missingVersionChangeJustificationMarker\n'
|
||||
'to your PR description with an explanation of why it is exempt.');
|
||||
'repository policy. If this is a false positive, please comment in '
|
||||
'the PR to explain why the PR is exempt, and add (or ask your '
|
||||
'reviewer to add) the "$_missingVersionChangeOverrideLabel" '
|
||||
'label.');
|
||||
return 'Missing version change';
|
||||
}
|
||||
}
|
||||
|
||||
if (!state.hasChangelogChange) {
|
||||
final String changeDescription = _getChangeDescription();
|
||||
if (changeDescription.split('\n').any((String line) =>
|
||||
line.startsWith(_missingChangelogChangeJustificationMarker))) {
|
||||
logWarning('Ignoring lack of CHANGELOG update due to '
|
||||
'"$_missingChangelogChangeJustificationMarker" in the '
|
||||
'change description.');
|
||||
} else if (_isAllowedDependabotChange(package, changeDescription)) {
|
||||
if (_prLabels.contains(_missingChangelogChangeOverrideLabel)) {
|
||||
logWarning('Ignoring lack of CHANGELOG update due to the '
|
||||
'"$_missingChangelogChangeOverrideLabel" label.');
|
||||
} else if (_isAllowedDependabotChange(package, _changeDescription)) {
|
||||
logWarning('Ignoring lack of CHANGELOG update for Dependabot change to '
|
||||
'a known internal dependency.');
|
||||
} else {
|
||||
printError(
|
||||
'No CHANGELOG change found. If this PR needs an exemption from '
|
||||
'the standard policy of listing all changes in the CHANGELOG, '
|
||||
'please add a line starting with\n'
|
||||
'$_missingChangelogChangeJustificationMarker\n'
|
||||
'to your PR description with an explanation of why.');
|
||||
'comment in the PR to explain why the PR is exempt, and add (or '
|
||||
'ask your reviewer to add) the '
|
||||
'"$_missingChangelogChangeOverrideLabel" label.');
|
||||
return 'Missing CHANGELOG change';
|
||||
}
|
||||
}
|
||||
@ -617,6 +621,11 @@ ${indentation}The first version listed in CHANGELOG.md is $fromChangeLog.
|
||||
/// Returns true if [changeDescription] matches a Dependabot change for a
|
||||
/// dependency roll that should bypass the normal version and CHANGELOG change
|
||||
/// checks (for dependencies that are known not to have client impact).
|
||||
///
|
||||
/// Depending on CI, [changeDescription] may either be the PR description, or
|
||||
/// the description of the last commit (see for example discussion in
|
||||
/// https://github.com/cirruslabs/cirrus-ci-docs/issues/1029), so this needs
|
||||
/// to handle both.
|
||||
bool _isAllowedDependabotChange(
|
||||
RepositoryPackage package, String changeDescription) {
|
||||
// Espresso exports some dependencies that are normally just internal test
|
||||
@ -629,8 +638,7 @@ ${indentation}The first version listed in CHANGELOG.md is $fromChangeLog.
|
||||
// any other PR, to identify Dependabot PRs.
|
||||
const String dependabotPRDescriptionMarker =
|
||||
'Dependabot commands and options';
|
||||
// The same thing, but for the Dependabot commit message, to work around
|
||||
// https://github.com/cirruslabs/cirrus-ci-docs/issues/1029.
|
||||
// The same thing, but for the Dependabot commit message.
|
||||
const String dependabotCommitMessageMarker =
|
||||
'Signed-off-by: dependabot[bot]';
|
||||
// Expression to extract the name of the dependency being updated.
|
||||
|
Reference in New Issue
Block a user