-
Notifications
You must be signed in to change notification settings - Fork 9.8k
[tool] add all
and dry-run
flags to publish-plugin command
#3776
Conversation
As we discussed in the doc, we are probably going to use the alternative if LUCI push to git works. |
all
and dry-run
flags to publish-plugin command
StreamSubscription<String> _stdinSubscription; | ||
|
||
@override | ||
Future<void> run() async { | ||
final String package = argResults[_packageOption] as String; | ||
if (package == null) { | ||
final bool all = argResults[_allFlag] as bool; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: how about publishAll
as the variable name so it's more descriptive.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
@@ -64,13 +68,31 @@ class PublishPluginCommand extends PluginCommand { | |||
// Flutter convention is to use "upstream" for the single source of truth, and "origin" for personal forks. | |||
defaultsTo: 'upstream', | |||
); | |||
argParser.addFlag( | |||
_allFlag, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we should call this flag all-changed
? --all
sounds more like it should do something like the Melos publish-all command.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sounds good! DONE
@@ -111,7 +135,74 @@ class PublishPluginCommand extends PluginCommand { | |||
} | |||
_print('Local repo is ready!'); | |||
|
|||
final Directory packageDir = _getPackageDir(package); | |||
if (all) { | |||
await _publishAllPackages( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similarly, _publishAllChangedPackages
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
final List<String> changedPubspecs = | ||
await gitVersionFinder.getChangedPubSpecs(); | ||
if (changedPubspecs.isEmpty) { | ||
_print('No version updates in this commit, exiting...'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"..." indicates more to follow, which seems odd for something that says it's exiting.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, remove the exit part.
await baseGitDir.runCommand(<String>['tag', '--sort=-committerdate']); | ||
final List<String> existingTags = (existingTagsResult.stdout as String) | ||
.split('\n') | ||
..removeWhere((element) => element == ''); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isEmpty
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
@@ -120,7 +211,50 @@ class PublishPluginCommand extends PluginCommand { | |||
remoteUrl: remoteUrl, | |||
shouldPushTag: shouldPushTag); | |||
} | |||
await _finishSuccesfully(); | |||
_print('Release ${packageDir.basename} successful.'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There aren't any bools for the sub-steps; does that mean they are fatal errors when something goes wrong?
If we try to release 3 packages, an error with one of them presumably shouldn't kill the whole thing, but instead move on to the next, and then at the end list all the successes and failures.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done. Made all sub-steps within publishing a plugin to return a bool instead of throw directly, then the main process will decide to throw depends on the returned value.
} | ||
|
||
if (pubspec.name == null) { | ||
printErrorAndExit(errorMessage: 'Fatal: Package name is null.'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same concerns here; if this is fatal, then all packages will fail, not just the one that's wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed, commented above.
final String latestTag = existingTags.isNotEmpty | ||
? existingTags | ||
.firstWhere((String tag) => tag.split('-v').first == pubspec.name) | ||
: ''; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can use orElse
here instead of checking isNotEmpty
.
In fact, I think without that change the current logic is wrong, since just because the set of tags isn't empty doesn't mean that this particular package has been released before, so it seems like this would throw as soon as we had a new plugin. (Which suggests there's a test case missing.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch! Thanks! Fixed and added a test for it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated per review comments. PTAL @stuartmorgan
@@ -64,13 +68,31 @@ class PublishPluginCommand extends PluginCommand { | |||
// Flutter convention is to use "upstream" for the single source of truth, and "origin" for personal forks. | |||
defaultsTo: 'upstream', | |||
); | |||
argParser.addFlag( | |||
_allFlag, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sounds good! DONE
StreamSubscription<String> _stdinSubscription; | ||
|
||
@override | ||
Future<void> run() async { | ||
final String package = argResults[_packageOption] as String; | ||
if (package == null) { | ||
final bool all = argResults[_allFlag] as bool; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
@@ -111,7 +135,74 @@ class PublishPluginCommand extends PluginCommand { | |||
} | |||
_print('Local repo is ready!'); | |||
|
|||
final Directory packageDir = _getPackageDir(package); | |||
if (all) { | |||
await _publishAllPackages( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
final List<String> changedPubspecs = | ||
await gitVersionFinder.getChangedPubSpecs(); | ||
if (changedPubspecs.isEmpty) { | ||
_print('No version updates in this commit, exiting...'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, remove the exit part.
await baseGitDir.runCommand(<String>['tag', '--sort=-committerdate']); | ||
final List<String> existingTags = (existingTagsResult.stdout as String) | ||
.split('\n') | ||
..removeWhere((element) => element == ''); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
@@ -120,7 +211,50 @@ class PublishPluginCommand extends PluginCommand { | |||
remoteUrl: remoteUrl, | |||
shouldPushTag: shouldPushTag); | |||
} | |||
await _finishSuccesfully(); | |||
_print('Release ${packageDir.basename} successful.'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done. Made all sub-steps within publishing a plugin to return a bool instead of throw directly, then the main process will decide to throw depends on the returned value.
} | ||
|
||
if (pubspec.name == null) { | ||
printErrorAndExit(errorMessage: 'Fatal: Package name is null.'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed, commented above.
final String latestTag = existingTags.isNotEmpty | ||
? existingTags | ||
.firstWhere((String tag) => tag.split('-v').first == pubspec.name) | ||
: ''; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch! Thanks! Fixed and added a test for it
{String remote, | ||
String remoteUrl, | ||
bool shouldPushTag, | ||
GitDir baseGitDir}) async { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Optional nit: add trailing commas here and below to improve formatting
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
if (packagesFailed.isNotEmpty) { | ||
return false; | ||
} | ||
return true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These four lines can be simplified to: return packagesFailed.isEmpty;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
if (!needsRelease) { | ||
continue; | ||
} | ||
} on ToolExit catch (e) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Catching a ToolExit
seems potentially very confusing. How about making _checkNeedsRelease return a release/norelease/failure enum?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, sounds good!
], | ||
workingDir: packageDir); | ||
} on ToolExit catch (e) { | ||
print(e); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why print
and _print
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oops, this was a testing code, removed
Future<bool> _checkGitStatus(Directory packageDir) async { | ||
io.ProcessResult statusResult; | ||
try { | ||
statusResult = await processRunner.runAndExitOnError( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The naming here suggests there's a version that doesn't exit on error, so we wouldn't need to catch ToolExits?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
runAndExitOnError
does something extra (printing error message in a specific format etc), if we don't use it, then we have to re-write that code. I think we should rename this method to run(bool logError = true, bool exitOnError = true...)
.
Actually, I just saw that the run
method that we have already has a exitOnError
flag which doesn't do anything, which suggests that we used to have it like this but somehow refactored into 2 methods. https://github.com/flutter/plugins/blob/master/script/tool/lib/src/common.dart#L507
I'm happy to do the refactoring in a separate PR! Then rebase this on top after that lands.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#3827 @stuartmorgan here you go
workingDir: packagesDir); | ||
} | ||
} on ToolExit catch (e) { | ||
print(e); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same question as above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same answer above :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@stuartmorgan Fixed all review comments as well as removing all the unnecessary try-catch. PTAL
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM with nits.
Future<void> _publishPlugin({@required Directory packageDir}) async { | ||
await _checkGitStatus(packageDir); | ||
await _publish(packageDir); | ||
// Returns `true` if needs to release the version, `false` if needs to skip |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix comment for new return type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
} | ||
if (packagesFailed.isNotEmpty) { | ||
_print( | ||
'Packages failed to release: ${packagesFailed.join(', ')}, see above for details.'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: "Failed to release the following packages:"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
if (pubspec.version == null) { | ||
_print('No version found. A package that ' | ||
'intentionally has no version should be marked ' | ||
'"publish_to: none".'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Fix the excessive line breaking here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
// The package does not need to be released. | ||
noRelease, | ||
|
||
// There's an error when trying to access if the package needs to be released. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: s/access if/determine whether/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
script/tool/test/util.dart
Outdated
@@ -85,14 +87,14 @@ Directory createFakePlugin( | |||
final Directory exampleDir = pluginDirectory.childDirectory('example') | |||
..createSync(); | |||
createFakePubspec(exampleDir, | |||
name: '${name}_example', isFlutter: isFlutter); | |||
name: '${name}_example', isFlutter: isFlutter, includeVersion: false, publish_to: 'none'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While you're touching the utils, could you fix the naming of this parameter? It should be publishTo
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
* upstream/master: (383 commits) Add implement and registerWith method to plugins (flutter#3833) Update third_party license checking (flutter#3844) [tool] add `all` and `dry-run` flags to publish-plugin command (flutter#3776) Re-add bin/ to flutter_plugin_tools (flutter#3839) switch from using 'tuneup' to analyze to 'dart analyze' (flutter#3837) [in_app_purchase] Federated iOS implementation (flutter#3832) Prep the tools for publishing (flutter#3836) [in_app_purchase] Make PurchaseDetails.status mandatory (flutter#3831) Fix grammatical error in contributing guide (flutter#3217) [google_sign_in_web] fix README typos. [tool] combine run and runAndExitOnError (flutter#3827) [camera] android-rework part 2: Android auto focus feature (flutter#3796) [in_app_purchase_platform_interface] Added additional fields to ProductDetails (flutter#3826) Move all null safety packages' min dart sdk to 2.12.0 (flutter#3822) [path_provider_*] code cleanup: sort directives (flutter#3823) [in_app_purchase] Implementation of platform interface (flutter#3781) [google_sign_in] Add todo WRT correctly setting X-Goog-AuthUser header (flutter#3819) [tools] fix version check command not working for new packages (flutter#3818) [camera] android-rework part 1: Base classes to support Android Camera features (flutter#3795) fix MD (flutter#3815) ...
Add a new
all
flag to thepublish plugin
command does the following:publish-plugin
works: publishing to pub, git tag release etc.Add a new
dry-run
flag to dry-run the publish and tag release process. This is for testing locally and ci without actually publishing or git tag anything.This command is going to be part of auto-publish workflow.
part of flutter/flutter#79830
Pre-launch Checklist
[shared_preferences]
///
).If you need help, consider asking for advice on the #hackers-new channel on Discord.