feat: add --confirm flag to release and patch commands (#3628)
This commit is contained in:
@@ -108,6 +108,13 @@ To target the latest release (e.g. the release that was most recently updated) u
|
||||
help: CommonArguments.noConfirmArg.description,
|
||||
negatable: false,
|
||||
)
|
||||
// Added for https://github.com/shorebirdtech/shorebird/issues/3223.
|
||||
// Can be removed fall 2026 or later.
|
||||
..addFlag(
|
||||
'confirm',
|
||||
negatable: false,
|
||||
hide: true,
|
||||
)
|
||||
..addOption(
|
||||
CommonArguments.exportOptionsPlistArg.name,
|
||||
help: CommonArguments.exportOptionsPlistArg.description,
|
||||
@@ -188,6 +195,9 @@ NOTE: this is ${styleBold.wrap('not')} recommended. Asset changes cannot be incl
|
||||
/// The target script, if provided.
|
||||
late String? target = results.findOption('target', argParser: argParser);
|
||||
|
||||
/// Whether to prompt for confirmation before creating the patch.
|
||||
bool get confirm => results['confirm'] == true;
|
||||
|
||||
/// Whether to allow changes in assets (--allow-asset-diffs).
|
||||
bool get allowAssetDiffs => results['allow-asset-diffs'] == true;
|
||||
|
||||
@@ -608,6 +618,13 @@ ${styleBold.wrap(lightGreen.wrap('🚀 Ready to publish a new patch!'))}
|
||||
|
||||
${summary.join('\n')}
|
||||
''');
|
||||
|
||||
if (confirm && shorebirdEnv.canAcceptUserInput) {
|
||||
if (!logger.confirm('Would you like to continue?', defaultValue: true)) {
|
||||
logger.info('Aborting.');
|
||||
throw ProcessExit(ExitCode.success.code);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Downloads the given [releaseArtifact].
|
||||
|
||||
@@ -129,6 +129,13 @@ Defaults to "latest" which builds using the latest stable Flutter version.''',
|
||||
help: CommonArguments.noConfirmArg.description,
|
||||
negatable: false,
|
||||
)
|
||||
// Added for https://github.com/shorebirdtech/shorebird/issues/3223.
|
||||
// Can be removed fall 2026 or later.
|
||||
..addFlag(
|
||||
'confirm',
|
||||
negatable: false,
|
||||
hide: true,
|
||||
)
|
||||
..addOption(
|
||||
'release-version',
|
||||
help: '''
|
||||
@@ -225,6 +232,9 @@ of the iOS app that is using this module. (aar and ios-framework only)''',
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether to prompt for confirmation before creating the release.
|
||||
bool get confirm => results['confirm'] == true;
|
||||
|
||||
/// The shorebird app ID for the current project.
|
||||
String get appId => shorebirdEnv.getShorebirdYaml()!.getAppId(flavor: flavor);
|
||||
|
||||
@@ -524,6 +534,13 @@ ${styleBold.wrap(lightGreen.wrap('🚀 Ready to create a new release!'))}
|
||||
|
||||
${summary.join('\n')}
|
||||
''');
|
||||
|
||||
if (confirm && shorebirdEnv.canAcceptUserInput) {
|
||||
if (!logger.confirm('Would you like to continue?', defaultValue: true)) {
|
||||
logger.info('Aborting.');
|
||||
throw ProcessExit(ExitCode.success.code);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Fetches the release with version [version] from the server or creates a
|
||||
|
||||
@@ -815,6 +815,94 @@ void main() {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
group('when --confirm is passed', () {
|
||||
setUp(() {
|
||||
when(() => argResults['confirm']).thenReturn(true);
|
||||
when(() => shorebirdEnv.canAcceptUserInput).thenReturn(true);
|
||||
});
|
||||
|
||||
group('when user confirms', () {
|
||||
setUp(() {
|
||||
when(
|
||||
() => logger.confirm(
|
||||
any(),
|
||||
defaultValue: any(named: 'defaultValue'),
|
||||
),
|
||||
).thenReturn(true);
|
||||
});
|
||||
|
||||
test('continues', () async {
|
||||
await expectLater(
|
||||
runWithOverrides(
|
||||
() => command.logPatchSummary(
|
||||
app: appMetadata,
|
||||
releaseVersion: releaseVersion,
|
||||
patcher: patcher,
|
||||
patchArtifactBundles: patchArtifactBundles,
|
||||
),
|
||||
),
|
||||
completes,
|
||||
);
|
||||
verify(
|
||||
() => logger.confirm(
|
||||
'Would you like to continue?',
|
||||
defaultValue: true,
|
||||
),
|
||||
).called(1);
|
||||
});
|
||||
});
|
||||
|
||||
group('when user declines', () {
|
||||
setUp(() {
|
||||
when(
|
||||
() => logger.confirm(
|
||||
any(),
|
||||
defaultValue: any(named: 'defaultValue'),
|
||||
),
|
||||
).thenReturn(false);
|
||||
});
|
||||
|
||||
test('exits with success and prints Aborting.', () async {
|
||||
await expectLater(
|
||||
runWithOverrides(
|
||||
() => command.logPatchSummary(
|
||||
app: appMetadata,
|
||||
releaseVersion: releaseVersion,
|
||||
patcher: patcher,
|
||||
patchArtifactBundles: patchArtifactBundles,
|
||||
),
|
||||
),
|
||||
exitsWithCode(ExitCode.success),
|
||||
);
|
||||
verify(() => logger.info('Aborting.')).called(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
group('when --confirm is not passed', () {
|
||||
setUp(() {
|
||||
when(() => argResults['confirm']).thenReturn(false);
|
||||
});
|
||||
|
||||
test('does not prompt for confirmation', () async {
|
||||
await expectLater(
|
||||
runWithOverrides(
|
||||
() => command.logPatchSummary(
|
||||
app: appMetadata,
|
||||
releaseVersion: releaseVersion,
|
||||
patcher: patcher,
|
||||
patchArtifactBundles: patchArtifactBundles,
|
||||
),
|
||||
),
|
||||
completes,
|
||||
);
|
||||
verifyNever(
|
||||
() =>
|
||||
logger.confirm(any(), defaultValue: any(named: 'defaultValue')),
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
group('when flutter install fails', () {
|
||||
|
||||
@@ -414,6 +414,69 @@ void main() {
|
||||
});
|
||||
});
|
||||
|
||||
group('when --confirm is passed', () {
|
||||
setUp(() {
|
||||
when(() => argResults['confirm']).thenReturn(true);
|
||||
when(() => shorebirdEnv.canAcceptUserInput).thenReturn(true);
|
||||
});
|
||||
|
||||
group('when user confirms', () {
|
||||
setUp(() {
|
||||
when(
|
||||
() => logger.confirm(
|
||||
any(),
|
||||
defaultValue: any(named: 'defaultValue'),
|
||||
),
|
||||
).thenReturn(true);
|
||||
});
|
||||
|
||||
test('continues', () async {
|
||||
await runWithOverrides(command.run);
|
||||
verify(
|
||||
() => logger.confirm(
|
||||
'Would you like to continue?',
|
||||
defaultValue: true,
|
||||
),
|
||||
).called(1);
|
||||
});
|
||||
});
|
||||
|
||||
group('when user declines', () {
|
||||
setUp(() {
|
||||
when(
|
||||
() => logger.confirm(
|
||||
any(),
|
||||
defaultValue: any(named: 'defaultValue'),
|
||||
),
|
||||
).thenReturn(false);
|
||||
});
|
||||
|
||||
test('exits with success and prints Aborting.', () async {
|
||||
await expectLater(
|
||||
runWithOverrides(command.run),
|
||||
exitsWithCode(ExitCode.success),
|
||||
);
|
||||
verify(() => logger.info('Aborting.')).called(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
group('when --confirm is not passed', () {
|
||||
setUp(() {
|
||||
when(() => argResults['confirm']).thenReturn(false);
|
||||
});
|
||||
|
||||
test('does not prompt for confirmation', () async {
|
||||
await runWithOverrides(command.run);
|
||||
verifyNever(
|
||||
() => logger.confirm(
|
||||
any(),
|
||||
defaultValue: any(named: 'defaultValue'),
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
group('when flavor and target are provided', () {
|
||||
const flavor = 'test-flavor';
|
||||
const target = 'test-target';
|
||||
|
||||
Reference in New Issue
Block a user