Unverified Commit 38dbbb17 authored by Christopher Fujino's avatar Christopher Fujino Committed by GitHub

[flutter_conductor] deprecate increment (#99189)

parent 31316991
...@@ -44,9 +44,13 @@ conductor start \ ...@@ -44,9 +44,13 @@ conductor start \
--engine-cherrypicks=72114dafe28c8700f1d5d629c6ae9d34172ba395 \ --engine-cherrypicks=72114dafe28c8700f1d5d629c6ae9d34172ba395 \
--framework-cherrypicks=a3e66b396746f6581b2b7efd1b0d0f0074215128,d8d853436206e86f416236b930e97779b143a100 \ --framework-cherrypicks=a3e66b396746f6581b2b7efd1b0d0f0074215128,d8d853436206e86f416236b930e97779b143a100 \
--dart-revision=4511eb2a779a612d9d6b2012123575013e0aef12 \ --dart-revision=4511eb2a779a612d9d6b2012123575013e0aef12 \
--increment=m
``` ```
The conductor will, based on the release channel and the presence/lack of
previous tags, determine which part of the release version should be
incremented. In the cases where this is not correct, the version can be
overridden with `--version-override=3.0.0`.
For more details on these command line arguments, see `conductor help start`. For more details on these command line arguments, see `conductor help start`.
This command will write to disk a state file that will persist until the release This command will write to disk a state file that will persist until the release
is completed. If you already have a persistent state file, this command will is completed. If you already have a persistent state file, this command will
......
...@@ -16,8 +16,6 @@ const List<String> kBaseReleaseChannels = <String>['stable', 'beta']; ...@@ -16,8 +16,6 @@ const List<String> kBaseReleaseChannels = <String>['stable', 'beta'];
const List<String> kReleaseChannels = <String>[...kBaseReleaseChannels, FrameworkRepository.defaultBranch]; const List<String> kReleaseChannels = <String>[...kBaseReleaseChannels, FrameworkRepository.defaultBranch];
const List<String> kReleaseIncrements = <String>['y', 'z', 'm', 'n'];
const String kReleaseDocumentationUrl = 'https://github.com/flutter/flutter/wiki/Flutter-Cherrypick-Process'; const String kReleaseDocumentationUrl = 'https://github.com/flutter/flutter/wiki/Flutter-Cherrypick-Process';
const String kLuciPackagingConsoleLink = 'https://ci.chromium.org/p/flutter/g/packaging/console'; const String kLuciPackagingConsoleLink = 'https://ci.chromium.org/p/flutter/g/packaging/console';
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
# //flutter/dev/tools/lib/proto # //flutter/dev/tools/lib/proto
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" DIR="$(cd "$(dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
DARTFMT="$DIR/../../../../bin/cache/dart-sdk/bin/dartfmt"
# Ensure dart-sdk is cached # Ensure dart-sdk is cached
"$DIR/../../../../bin/dart" --version "$DIR/../../../../bin/dart" --version
...@@ -29,7 +28,7 @@ protoc --dart_out="$DIR" --proto_path="$DIR" "$DIR/conductor_state.proto" ...@@ -29,7 +28,7 @@ protoc --dart_out="$DIR" --proto_path="$DIR" "$DIR/conductor_state.proto"
for SOURCE_FILE in $(ls "$DIR"/*.pb*.dart); do for SOURCE_FILE in $(ls "$DIR"/*.pb*.dart); do
# Format in place file # Format in place file
"$DARTFMT" --overwrite --line-length 120 "$SOURCE_FILE" dart format --output=write --line-length 120 "$SOURCE_FILE"
# Create temp copy with the license header prepended # Create temp copy with the license header prepended
cp "$DIR/license_header.txt" "${SOURCE_FILE}.tmp" cp "$DIR/license_header.txt" "${SOURCE_FILE}.tmp"
......
...@@ -403,8 +403,12 @@ class ConductorState extends $pb.GeneratedMessage { ...@@ -403,8 +403,12 @@ class ConductorState extends $pb.GeneratedMessage {
enumValues: ReleasePhase.values) enumValues: ReleasePhase.values)
..aOS(10, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'conductorVersion', ..aOS(10, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'conductorVersion',
protoName: 'conductorVersion') protoName: 'conductorVersion')
..aOS(11, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'incrementLevel', ..e<ReleaseType>(
protoName: 'incrementLevel') 11, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'releaseType', $pb.PbFieldType.OE,
protoName: 'releaseType',
defaultOrMaker: ReleaseType.STABLE_INITIAL,
valueOf: ReleaseType.valueOf,
enumValues: ReleaseType.values)
..hasRequiredFields = false; ..hasRequiredFields = false;
ConductorState._() : super(); ConductorState._() : super();
...@@ -418,7 +422,7 @@ class ConductorState extends $pb.GeneratedMessage { ...@@ -418,7 +422,7 @@ class ConductorState extends $pb.GeneratedMessage {
$core.Iterable<$core.String>? logs, $core.Iterable<$core.String>? logs,
ReleasePhase? currentPhase, ReleasePhase? currentPhase,
$core.String? conductorVersion, $core.String? conductorVersion,
$core.String? incrementLevel, ReleaseType? releaseType,
}) { }) {
final _result = create(); final _result = create();
if (releaseChannel != null) { if (releaseChannel != null) {
...@@ -448,8 +452,8 @@ class ConductorState extends $pb.GeneratedMessage { ...@@ -448,8 +452,8 @@ class ConductorState extends $pb.GeneratedMessage {
if (conductorVersion != null) { if (conductorVersion != null) {
_result.conductorVersion = conductorVersion; _result.conductorVersion = conductorVersion;
} }
if (incrementLevel != null) { if (releaseType != null) {
_result.incrementLevel = incrementLevel; _result.releaseType = releaseType;
} }
return _result; return _result;
} }
...@@ -580,14 +584,14 @@ class ConductorState extends $pb.GeneratedMessage { ...@@ -580,14 +584,14 @@ class ConductorState extends $pb.GeneratedMessage {
void clearConductorVersion() => clearField(10); void clearConductorVersion() => clearField(10);
@$pb.TagNumber(11) @$pb.TagNumber(11)
$core.String get incrementLevel => $_getSZ(9); ReleaseType get releaseType => $_getN(9);
@$pb.TagNumber(11) @$pb.TagNumber(11)
set incrementLevel($core.String v) { set releaseType(ReleaseType v) {
$_setString(9, v); setField(11, v);
} }
@$pb.TagNumber(11) @$pb.TagNumber(11)
$core.bool hasIncrementLevel() => $_has(9); $core.bool hasReleaseType() => $_has(9);
@$pb.TagNumber(11) @$pb.TagNumber(11)
void clearIncrementLevel() => clearField(11); void clearReleaseType() => clearField(11);
} }
...@@ -67,3 +67,26 @@ class CherrypickState extends $pb.ProtobufEnum { ...@@ -67,3 +67,26 @@ class CherrypickState extends $pb.ProtobufEnum {
const CherrypickState._($core.int v, $core.String n) : super(v, n); const CherrypickState._($core.int v, $core.String n) : super(v, n);
} }
class ReleaseType extends $pb.ProtobufEnum {
static const ReleaseType STABLE_INITIAL =
ReleaseType._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'STABLE_INITIAL');
static const ReleaseType STABLE_HOTFIX =
ReleaseType._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'STABLE_HOTFIX');
static const ReleaseType BETA_INITIAL =
ReleaseType._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'BETA_INITIAL');
static const ReleaseType BETA_HOTFIX =
ReleaseType._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'BETA_HOTFIX');
static const $core.List<ReleaseType> values = <ReleaseType>[
STABLE_INITIAL,
STABLE_HOTFIX,
BETA_INITIAL,
BETA_HOTFIX,
];
static final $core.Map<$core.int, ReleaseType> _byValue = $pb.ProtobufEnum.initByValue(values);
static ReleaseType? valueOf($core.int value) => _byValue[value];
const ReleaseType._($core.int v, $core.String n) : super(v, n);
}
...@@ -44,6 +44,20 @@ const CherrypickState$json = const { ...@@ -44,6 +44,20 @@ const CherrypickState$json = const {
/// Descriptor for `CherrypickState`. Decode as a `google.protobuf.EnumDescriptorProto`. /// Descriptor for `CherrypickState`. Decode as a `google.protobuf.EnumDescriptorProto`.
final $typed_data.Uint8List cherrypickStateDescriptor = $convert.base64Decode( final $typed_data.Uint8List cherrypickStateDescriptor = $convert.base64Decode(
'Cg9DaGVycnlwaWNrU3RhdGUSCwoHUEVORElORxAAEhkKFVBFTkRJTkdfV0lUSF9DT05GTElDVBABEg0KCUNPTVBMRVRFRBACEg0KCUFCQU5ET05FRBAD'); 'Cg9DaGVycnlwaWNrU3RhdGUSCwoHUEVORElORxAAEhkKFVBFTkRJTkdfV0lUSF9DT05GTElDVBABEg0KCUNPTVBMRVRFRBACEg0KCUFCQU5ET05FRBAD');
@$core.Deprecated('Use releaseTypeDescriptor instead')
const ReleaseType$json = const {
'1': 'ReleaseType',
'2': const [
const {'1': 'STABLE_INITIAL', '2': 0},
const {'1': 'STABLE_HOTFIX', '2': 1},
const {'1': 'BETA_INITIAL', '2': 2},
const {'1': 'BETA_HOTFIX', '2': 3},
],
};
/// Descriptor for `ReleaseType`. Decode as a `google.protobuf.EnumDescriptorProto`.
final $typed_data.Uint8List releaseTypeDescriptor = $convert.base64Decode(
'CgtSZWxlYXNlVHlwZRISCg5TVEFCTEVfSU5JVElBTBAAEhEKDVNUQUJMRV9IT1RGSVgQARIQCgxCRVRBX0lOSVRJQUwQAhIPCgtCRVRBX0hPVEZJWBAD');
@$core.Deprecated('Use remoteDescriptor instead') @$core.Deprecated('Use remoteDescriptor instead')
const Remote$json = const { const Remote$json = const {
'1': 'Remote', '1': 'Remote',
...@@ -101,10 +115,10 @@ const ConductorState$json = const { ...@@ -101,10 +115,10 @@ const ConductorState$json = const {
const {'1': 'logs', '3': 8, '4': 3, '5': 9, '10': 'logs'}, const {'1': 'logs', '3': 8, '4': 3, '5': 9, '10': 'logs'},
const {'1': 'currentPhase', '3': 9, '4': 1, '5': 14, '6': '.conductor_state.ReleasePhase', '10': 'currentPhase'}, const {'1': 'currentPhase', '3': 9, '4': 1, '5': 14, '6': '.conductor_state.ReleasePhase', '10': 'currentPhase'},
const {'1': 'conductorVersion', '3': 10, '4': 1, '5': 9, '10': 'conductorVersion'}, const {'1': 'conductorVersion', '3': 10, '4': 1, '5': 9, '10': 'conductorVersion'},
const {'1': 'incrementLevel', '3': 11, '4': 1, '5': 9, '10': 'incrementLevel'}, const {'1': 'releaseType', '3': 11, '4': 1, '5': 14, '6': '.conductor_state.ReleaseType', '10': 'releaseType'},
], ],
}; };
/// Descriptor for `ConductorState`. Decode as a `google.protobuf.DescriptorProto`. /// Descriptor for `ConductorState`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List conductorStateDescriptor = $convert.base64Decode( final $typed_data.Uint8List conductorStateDescriptor = $convert.base64Decode(
'Cg5Db25kdWN0b3JTdGF0ZRImCg5yZWxlYXNlQ2hhbm5lbBgBIAEoCVIOcmVsZWFzZUNoYW5uZWwSJgoOcmVsZWFzZVZlcnNpb24YAiABKAlSDnJlbGVhc2VWZXJzaW9uEjMKBmVuZ2luZRgEIAEoCzIbLmNvbmR1Y3Rvcl9zdGF0ZS5SZXBvc2l0b3J5UgZlbmdpbmUSOQoJZnJhbWV3b3JrGAUgASgLMhsuY29uZHVjdG9yX3N0YXRlLlJlcG9zaXRvcnlSCWZyYW1ld29yaxIgCgtjcmVhdGVkRGF0ZRgGIAEoA1ILY3JlYXRlZERhdGUSKAoPbGFzdFVwZGF0ZWREYXRlGAcgASgDUg9sYXN0VXBkYXRlZERhdGUSEgoEbG9ncxgIIAMoCVIEbG9ncxJBCgxjdXJyZW50UGhhc2UYCSABKA4yHS5jb25kdWN0b3Jfc3RhdGUuUmVsZWFzZVBoYXNlUgxjdXJyZW50UGhhc2USKgoQY29uZHVjdG9yVmVyc2lvbhgKIAEoCVIQY29uZHVjdG9yVmVyc2lvbhImCg5pbmNyZW1lbnRMZXZlbBgLIAEoCVIOaW5jcmVtZW50TGV2ZWw='); 'Cg5Db25kdWN0b3JTdGF0ZRImCg5yZWxlYXNlQ2hhbm5lbBgBIAEoCVIOcmVsZWFzZUNoYW5uZWwSJgoOcmVsZWFzZVZlcnNpb24YAiABKAlSDnJlbGVhc2VWZXJzaW9uEjMKBmVuZ2luZRgEIAEoCzIbLmNvbmR1Y3Rvcl9zdGF0ZS5SZXBvc2l0b3J5UgZlbmdpbmUSOQoJZnJhbWV3b3JrGAUgASgLMhsuY29uZHVjdG9yX3N0YXRlLlJlcG9zaXRvcnlSCWZyYW1ld29yaxIgCgtjcmVhdGVkRGF0ZRgGIAEoA1ILY3JlYXRlZERhdGUSKAoPbGFzdFVwZGF0ZWREYXRlGAcgASgDUg9sYXN0VXBkYXRlZERhdGUSEgoEbG9ncxgIIAMoCVIEbG9ncxJBCgxjdXJyZW50UGhhc2UYCSABKA4yHS5jb25kdWN0b3Jfc3RhdGUuUmVsZWFzZVBoYXNlUgxjdXJyZW50UGhhc2USKgoQY29uZHVjdG9yVmVyc2lvbhgKIAEoCVIQY29uZHVjdG9yVmVyc2lvbhI+CgtyZWxlYXNlVHlwZRgLIAEoDjIcLmNvbmR1Y3Rvcl9zdGF0ZS5SZWxlYXNlVHlwZVILcmVsZWFzZVR5cGU=');
...@@ -45,6 +45,24 @@ enum CherrypickState { ...@@ -45,6 +45,24 @@ enum CherrypickState {
ABANDONED = 3; ABANDONED = 3;
} }
// The type of release that is being created.
//
// This determines how the version will be calculated.
enum ReleaseType {
// All pre-release metadata from previous beta releases will be discarded. The
// z must be 0.
STABLE_INITIAL = 0;
// Increment z.
STABLE_HOTFIX = 1;
// Compute x, y, and m from the candidate branch name. z and n should be 0.
BETA_INITIAL = 2;
// Increment n.
BETA_HOTFIX = 3;
}
message Cherrypick { message Cherrypick {
// The revision on trunk to cherrypick. // The revision on trunk to cherrypick.
string trunkRevision = 1; string trunkRevision = 1;
...@@ -113,6 +131,5 @@ message ConductorState { ...@@ -113,6 +131,5 @@ message ConductorState {
// that created the [ConductorState] object. // that created the [ConductorState] object.
string conductorVersion = 10; string conductorVersion = 10;
// One of x, y, z, m, or n. ReleaseType releaseType = 11;
string incrementLevel = 11;
} }
...@@ -6,6 +6,7 @@ import 'package:args/args.dart'; ...@@ -6,6 +6,7 @@ import 'package:args/args.dart';
import 'package:args/command_runner.dart'; import 'package:args/command_runner.dart';
import 'package:file/file.dart'; import 'package:file/file.dart';
import 'package:fixnum/fixnum.dart'; import 'package:fixnum/fixnum.dart';
import 'package:meta/meta.dart';
import 'package:platform/platform.dart'; import 'package:platform/platform.dart';
import 'package:process/process.dart'; import 'package:process/process.dart';
...@@ -13,7 +14,7 @@ import 'context.dart'; ...@@ -13,7 +14,7 @@ import 'context.dart';
import 'git.dart'; import 'git.dart';
import 'globals.dart'; import 'globals.dart';
import 'proto/conductor_state.pb.dart' as pb; import 'proto/conductor_state.pb.dart' as pb;
import 'proto/conductor_state.pbenum.dart' show ReleasePhase; import 'proto/conductor_state.pbenum.dart';
import 'repository.dart'; import 'repository.dart';
import 'state.dart' as state_import; import 'state.dart' as state_import;
import 'stdio.dart'; import 'stdio.dart';
...@@ -26,10 +27,10 @@ const String kEngineUpstreamOption = 'engine-upstream'; ...@@ -26,10 +27,10 @@ const String kEngineUpstreamOption = 'engine-upstream';
const String kFrameworkCherrypicksOption = 'framework-cherrypicks'; const String kFrameworkCherrypicksOption = 'framework-cherrypicks';
const String kFrameworkMirrorOption = 'framework-mirror'; const String kFrameworkMirrorOption = 'framework-mirror';
const String kFrameworkUpstreamOption = 'framework-upstream'; const String kFrameworkUpstreamOption = 'framework-upstream';
const String kIncrementOption = 'increment';
const String kEngineMirrorOption = 'engine-mirror'; const String kEngineMirrorOption = 'engine-mirror';
const String kReleaseOption = 'release-channel'; const String kReleaseOption = 'release-channel';
const String kStateOption = 'state-file'; const String kStateOption = 'state-file';
const String kVersionOverrideOption = 'version-override';
/// Command to print the status of the current Flutter release. /// Command to print the status of the current Flutter release.
class StartCommand extends Command<void> { class StartCommand extends Command<void> {
...@@ -89,23 +90,16 @@ class StartCommand extends Command<void> { ...@@ -89,23 +90,16 @@ class StartCommand extends Command<void> {
kDartRevisionOption, kDartRevisionOption,
help: 'New Dart revision to cherrypick.', help: 'New Dart revision to cherrypick.',
); );
argParser.addOption(
kIncrementOption,
help: 'Specifies which part of the x.y.z version number to increment. Required.',
valueHelp: 'level',
allowed: kReleaseIncrements,
allowedHelp: <String, String>{
'y': 'Indicates the first dev release after a beta release.',
'z': 'Indicates a hotfix to a stable release.',
'm': 'Indicates a standard dev release.',
'n': 'Indicates a hotfix to a dev or beta release.',
},
);
argParser.addFlag( argParser.addFlag(
kForceFlag, kForceFlag,
abbr: 'f', abbr: 'f',
help: 'Override all validations of the command line inputs.', help: 'Override all validations of the command line inputs.',
); );
argParser.addOption(
kVersionOverrideOption,
help: 'Explicitly set the desired version. This should only be used if '
'the version computed by the tool is not correct.',
);
} }
final Checkouts checkouts; final Checkouts checkouts;
...@@ -177,11 +171,6 @@ class StartCommand extends Command<void> { ...@@ -177,11 +171,6 @@ class StartCommand extends Command<void> {
platform.environment, platform.environment,
allowNull: true, allowNull: true,
); );
final String incrementLetter = getValueFromEnvOrArgs(
kIncrementOption,
argumentResults,
platform.environment,
)!;
final bool force = getBoolFromEnvOrArgs( final bool force = getBoolFromEnvOrArgs(
kForceFlag, kForceFlag,
argumentResults, argumentResults,
...@@ -190,6 +179,16 @@ class StartCommand extends Command<void> { ...@@ -190,6 +179,16 @@ class StartCommand extends Command<void> {
final File stateFile = checkouts.fileSystem.file( final File stateFile = checkouts.fileSystem.file(
getValueFromEnvOrArgs(kStateOption, argumentResults, platform.environment), getValueFromEnvOrArgs(kStateOption, argumentResults, platform.environment),
); );
final String? versionOverrideString = getValueFromEnvOrArgs(
kVersionOverrideOption,
argumentResults,
platform.environment,
allowNull: true,
);
Version? versionOverride;
if (versionOverrideString != null) {
versionOverride = Version.fromString(versionOverrideString);
}
final StartContext context = StartContext( final StartContext context = StartContext(
candidateBranch: candidateBranch, candidateBranch: candidateBranch,
...@@ -202,11 +201,11 @@ class StartCommand extends Command<void> { ...@@ -202,11 +201,11 @@ class StartCommand extends Command<void> {
frameworkCherrypickRevisions: frameworkCherrypickRevisions, frameworkCherrypickRevisions: frameworkCherrypickRevisions,
frameworkMirror: frameworkMirror, frameworkMirror: frameworkMirror,
frameworkUpstream: frameworkUpstream, frameworkUpstream: frameworkUpstream,
incrementLetter: incrementLetter,
processManager: processManager, processManager: processManager,
releaseChannel: releaseChannel, releaseChannel: releaseChannel,
stateFile: stateFile, stateFile: stateFile,
force: force, force: force,
versionOverride: versionOverride,
); );
return context.run(); return context.run();
} }
...@@ -226,12 +225,12 @@ class StartContext extends Context { ...@@ -226,12 +225,12 @@ class StartContext extends Context {
required this.frameworkMirror, required this.frameworkMirror,
required this.frameworkUpstream, required this.frameworkUpstream,
required this.conductorVersion, required this.conductorVersion,
required this.incrementLetter,
required this.processManager, required this.processManager,
required this.releaseChannel, required this.releaseChannel,
required Checkouts checkouts, required Checkouts checkouts,
required File stateFile, required File stateFile,
this.force = false, this.force = false,
this.versionOverride,
}) : git = Git(processManager), }) : git = Git(processManager),
engine = EngineRepository( engine = EngineRepository(
checkouts, checkouts,
...@@ -270,10 +269,10 @@ class StartContext extends Context { ...@@ -270,10 +269,10 @@ class StartContext extends Context {
final String frameworkMirror; final String frameworkMirror;
final String frameworkUpstream; final String frameworkUpstream;
final String conductorVersion; final String conductorVersion;
final String incrementLetter;
final Git git; final Git git;
final ProcessManager processManager; final ProcessManager processManager;
final String releaseChannel; final String releaseChannel;
final Version? versionOverride;
/// If validations should be overridden. /// If validations should be overridden.
final bool force; final bool force;
...@@ -281,6 +280,26 @@ class StartContext extends Context { ...@@ -281,6 +280,26 @@ class StartContext extends Context {
final EngineRepository engine; final EngineRepository engine;
final FrameworkRepository framework; final FrameworkRepository framework;
/// Determine which part of the version to increment in the next release.
///
/// If [atBranchPoint] is true, then this is a [ReleaseType.BETA_INITIAL].
@visibleForTesting
ReleaseType computeReleaseType(Version lastVersion, bool atBranchPoint) {
if (atBranchPoint) {
return ReleaseType.BETA_INITIAL;
}
if (releaseChannel == 'stable') {
if (lastVersion.type == VersionType.stable) {
return ReleaseType.STABLE_HOTFIX;
} else {
return ReleaseType.STABLE_INITIAL;
}
}
return ReleaseType.BETA_HOTFIX;
}
Future<void> run() async { Future<void> run() async {
if (stateFile.existsSync()) { if (stateFile.existsSync()) {
throw ConductorException('Error! A persistent state file already found at ${stateFile.path}.\n\n' throw ConductorException('Error! A persistent state file already found at ${stateFile.path}.\n\n'
...@@ -299,7 +318,6 @@ class StartContext extends Context { ...@@ -299,7 +318,6 @@ class StartContext extends Context {
state.releaseChannel = releaseChannel; state.releaseChannel = releaseChannel;
state.createdDate = unixDate; state.createdDate = unixDate;
state.lastUpdatedDate = unixDate; state.lastUpdatedDate = unixDate;
state.incrementLevel = incrementLetter;
// Create a new branch so that we don't accidentally push to upstream // Create a new branch so that we don't accidentally push to upstream
// candidateBranch. // candidateBranch.
...@@ -378,21 +396,34 @@ class StartContext extends Context { ...@@ -378,21 +396,34 @@ class StartContext extends Context {
exact: false, exact: false,
)); ));
final String frameworkHead = await framework.reverseParse('HEAD');
final String branchPoint = await framework.branchPoint(candidateBranch, FrameworkRepository.defaultBranch);
final bool atBranchPoint = branchPoint == frameworkHead;
final ReleaseType releaseType = computeReleaseType(lastVersion, atBranchPoint);
state.releaseType = releaseType;
try { try {
lastVersion.ensureValid(candidateBranch, incrementLetter); lastVersion.ensureValid(candidateBranch, releaseType);
} on ConductorException catch (e) { } on ConductorException catch (e) {
// Let the user know, but resume execution // Let the user know, but resume execution
stdio.printError(e.message); stdio.printError(e.message);
} }
Version nextVersion = calculateNextVersion(lastVersion); Version nextVersion;
if (!force) { if (versionOverride != null) {
nextVersion = await ensureBranchPointTagged(nextVersion, framework); nextVersion = versionOverride!;
} else {
nextVersion = calculateNextVersion(lastVersion, releaseType);
nextVersion = await ensureBranchPointTagged(
branchPoint: branchPoint,
requestedVersion: nextVersion,
framework: framework,
);
} }
state.releaseVersion = nextVersion.toString(); state.releaseVersion = nextVersion.toString();
final String frameworkHead = await framework.reverseParse('HEAD');
state.framework = pb.Repository( state.framework = pb.Repository(
candidateBranch: candidateBranch, candidateBranch: candidateBranch,
workingBranch: workingBranchName, workingBranch: workingBranchName,
...@@ -416,37 +447,39 @@ class StartContext extends Context { ...@@ -416,37 +447,39 @@ class StartContext extends Context {
} }
/// Determine this release's version number from the [lastVersion] and the [incrementLetter]. /// Determine this release's version number from the [lastVersion] and the [incrementLetter].
Version calculateNextVersion(Version lastVersion) { Version calculateNextVersion(Version lastVersion, ReleaseType releaseType) {
if (incrementLetter == 'm') { late final Version nextVersion;
return Version.fromCandidateBranch(candidateBranch); switch (releaseType) {
case ReleaseType.STABLE_INITIAL:
nextVersion = Version(
x: lastVersion.x,
y: lastVersion.y,
z: 0,
type: VersionType.stable,
);
break;
case ReleaseType.STABLE_HOTFIX:
nextVersion = Version.increment(lastVersion, 'z');
break;
case ReleaseType.BETA_INITIAL:
nextVersion = Version.fromCandidateBranch(candidateBranch);
break;
case ReleaseType.BETA_HOTFIX:
nextVersion = Version.increment(lastVersion, 'n');
break;
} }
if (incrementLetter == 'z') { return nextVersion;
if (lastVersion.type == VersionType.stable) {
return Version.increment(lastVersion, incrementLetter);
}
// This is the first stable release, so hardcode the z as 0
return Version(
x: lastVersion.x,
y: lastVersion.y,
z: 0,
type: VersionType.stable,
);
}
return Version.increment(lastVersion, incrementLetter);
} }
/// Ensures the branch point [candidateBranch] and `master` has a version tag. /// Ensures the branch point [candidateBranch] and `master` has a version tag.
/// ///
/// This is necessary for version reporting for users on the `master` channel /// This is necessary for version reporting for users on the `master` channel
/// to be correct. /// to be correct.
Future<Version> ensureBranchPointTagged( Future<Version> ensureBranchPointTagged({
Version requestedVersion, required Version requestedVersion,
FrameworkRepository framework, required String branchPoint,
) async { required FrameworkRepository framework,
final String branchPoint = await framework.branchPoint( }) async {
candidateBranch,
FrameworkRepository.defaultBranch,
);
if (await framework.isCommitTagged(branchPoint)) { if (await framework.isCommitTagged(branchPoint)) {
// The branch point is tagged, no work to be done // The branch point is tagged, no work to be done
return requestedVersion; return requestedVersion;
......
...@@ -2,7 +2,9 @@ ...@@ -2,7 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import './globals.dart' show ConductorException, kReleaseIncrements, releaseCandidateBranchRegex; import 'globals.dart' show ConductorException, releaseCandidateBranchRegex;
import 'proto/conductor_state.pbenum.dart';
/// Possible string formats that `flutter --version` can return. /// Possible string formats that `flutter --version` can return.
enum VersionType { enum VersionType {
...@@ -262,10 +264,7 @@ class Version { ...@@ -262,10 +264,7 @@ class Version {
/// ///
/// Will throw a [ConductorException] if the version is not possible given the /// Will throw a [ConductorException] if the version is not possible given the
/// [candidateBranch] and [incrementLetter]. /// [candidateBranch] and [incrementLetter].
void ensureValid(String candidateBranch, String incrementLetter) { void ensureValid(String candidateBranch, ReleaseType releaseType) {
if (!kReleaseIncrements.contains(incrementLetter)) {
throw ConductorException('Invalid incrementLetter: $incrementLetter');
}
final RegExpMatch? branchMatch = releaseCandidateBranchRegex.firstMatch(candidateBranch); final RegExpMatch? branchMatch = releaseCandidateBranchRegex.firstMatch(candidateBranch);
if (branchMatch == null) { if (branchMatch == null) {
throw ConductorException( throw ConductorException(
...@@ -292,12 +291,12 @@ class Version { ...@@ -292,12 +291,12 @@ class Version {
} }
// stable type versions don't have an m field set // stable type versions don't have an m field set
if (type != VersionType.stable && incrementLetter != 'm') { if (type != VersionType.stable && releaseType != ReleaseType.STABLE_HOTFIX && releaseType != ReleaseType.STABLE_INITIAL) {
final String branchM = branchMatch.group(3)!; final String branchM = branchMatch.group(3)!;
if (m != int.tryParse(branchM)) { if (m != int.tryParse(branchM)) {
throw ConductorException( throw ConductorException(
'Parsed version ${toString()} has a different m value than candidate ' 'Parsed version ${toString()} has a different m value than candidate '
'branch $candidateBranch', 'branch $candidateBranch with type $type',
); );
} }
} }
......
This diff is collapsed.
...@@ -18,7 +18,6 @@ void main() { ...@@ -18,7 +18,6 @@ void main() {
final pb.ConductorState state = pb.ConductorState( final pb.ConductorState state = pb.ConductorState(
releaseChannel: 'stable', releaseChannel: 'stable',
releaseVersion: '2.3.4', releaseVersion: '2.3.4',
incrementLevel: 'z',
engine: pb.Repository( engine: pb.Repository(
candidateBranch: candidateBranch, candidateBranch: candidateBranch,
upstream: pb.Remote( upstream: pb.Remote(
...@@ -60,8 +59,7 @@ void main() { ...@@ -60,8 +59,7 @@ void main() {
}, },
"logs": [ "logs": [
"[status] hello world" "[status] hello world"
], ]
"incrementLevel": "z"
}'''; }''';
expect(serializedState, expectedString); expect(serializedState, expectedString);
}); });
......
...@@ -2,9 +2,10 @@ ...@@ -2,9 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'package:conductor_core/src/proto/conductor_state.pbenum.dart';
import 'package:conductor_core/src/version.dart'; import 'package:conductor_core/src/version.dart';
import './common.dart'; import 'common.dart';
void main() { void main() {
group('Version.fromString()', () { group('Version.fromString()', () {
...@@ -106,7 +107,7 @@ void main() { ...@@ -106,7 +107,7 @@ void main() {
const String candidateBranch = 'flutter-3.2-candidate.4'; const String candidateBranch = 'flutter-3.2-candidate.4';
final Version version = Version.fromString(versionString); final Version version = Version.fromString(versionString);
expect( expect(
() => version.ensureValid(candidateBranch, 'n'), () => version.ensureValid(candidateBranch, ReleaseType.BETA_HOTFIX),
throwsExceptionWith( throwsExceptionWith(
'Parsed version $versionString has a different x value than ' 'Parsed version $versionString has a different x value than '
'candidate branch $candidateBranch', 'candidate branch $candidateBranch',
...@@ -119,7 +120,7 @@ void main() { ...@@ -119,7 +120,7 @@ void main() {
const String candidateBranch = 'flutter-1.15-candidate.4'; const String candidateBranch = 'flutter-1.15-candidate.4';
final Version version = Version.fromString(versionString); final Version version = Version.fromString(versionString);
expect( expect(
() => version.ensureValid(candidateBranch, 'm'), () => version.ensureValid(candidateBranch, ReleaseType.BETA_INITIAL),
throwsExceptionWith( throwsExceptionWith(
'Parsed version $versionString has a different y value than ' 'Parsed version $versionString has a different y value than '
'candidate branch $candidateBranch', 'candidate branch $candidateBranch',
...@@ -132,7 +133,7 @@ void main() { ...@@ -132,7 +133,7 @@ void main() {
const String candidateBranch = 'flutter-1.2-candidate.0'; const String candidateBranch = 'flutter-1.2-candidate.0';
final Version version = Version.fromString(versionString); final Version version = Version.fromString(versionString);
expect( expect(
() => version.ensureValid(candidateBranch, 'n'), () => version.ensureValid(candidateBranch, ReleaseType.BETA_HOTFIX),
throwsExceptionWith( throwsExceptionWith(
'Parsed version $versionString has a different m value than ' 'Parsed version $versionString has a different m value than '
'candidate branch $candidateBranch', 'candidate branch $candidateBranch',
...@@ -145,7 +146,7 @@ void main() { ...@@ -145,7 +146,7 @@ void main() {
const String candidateBranch = 'flutter-1.2-candidate.98'; const String candidateBranch = 'flutter-1.2-candidate.98';
final Version version = Version.fromString(versionString); final Version version = Version.fromString(versionString);
expect( expect(
() => version.ensureValid(candidateBranch, 'n'), () => version.ensureValid(candidateBranch, ReleaseType.STABLE_HOTFIX),
isNot(throwsException), isNot(throwsException),
); );
}); });
...@@ -155,21 +156,11 @@ void main() { ...@@ -155,21 +156,11 @@ void main() {
const String candidateBranch = 'stable'; const String candidateBranch = 'stable';
final Version version = Version.fromString(versionString); final Version version = Version.fromString(versionString);
expect( expect(
() => version.ensureValid(candidateBranch, 'z'), () => version.ensureValid(candidateBranch, ReleaseType.STABLE_HOTFIX),
throwsExceptionWith( throwsExceptionWith(
'Candidate branch $candidateBranch does not match the pattern', 'Candidate branch $candidateBranch does not match the pattern',
), ),
); );
}); });
test('does not validate m if incrementLetter is m', () {
const String versionString = '1.2.0-0.0.pre';
const String candidateBranch = 'flutter-1.2-candidate.42';
final Version version = Version.fromString(versionString);
expect(
() => version.ensureValid(candidateBranch, 'm'),
isNot(throwsException),
);
});
}); });
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment