mirror of
https://github.com/flutter/packages.git
synced 2025-05-29 20:39:56 +08:00
[tool] add all
and dry-run
flags to publish-plugin command (#3776)
This commit is contained in:
@ -4,12 +4,14 @@
|
|||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
import 'dart:io' as io;
|
||||||
|
|
||||||
import 'package:file/file.dart';
|
import 'package:file/file.dart';
|
||||||
import 'package:git/git.dart';
|
import 'package:git/git.dart';
|
||||||
import 'package:meta/meta.dart';
|
import 'package:meta/meta.dart';
|
||||||
import 'package:path/path.dart' as p;
|
import 'package:path/path.dart' as p;
|
||||||
|
import 'package:pub_semver/pub_semver.dart';
|
||||||
|
import 'package:pubspec_parse/pubspec_parse.dart';
|
||||||
import 'package:yaml/yaml.dart';
|
import 'package:yaml/yaml.dart';
|
||||||
|
|
||||||
import 'common.dart';
|
import 'common.dart';
|
||||||
@ -32,10 +34,12 @@ class PublishPluginCommand extends PluginCommand {
|
|||||||
FileSystem fileSystem, {
|
FileSystem fileSystem, {
|
||||||
ProcessRunner processRunner = const ProcessRunner(),
|
ProcessRunner processRunner = const ProcessRunner(),
|
||||||
Print print = print,
|
Print print = print,
|
||||||
Stdin stdinput,
|
io.Stdin stdinput,
|
||||||
|
GitDir gitDir,
|
||||||
}) : _print = print,
|
}) : _print = print,
|
||||||
_stdin = stdinput ?? stdin,
|
_stdin = stdinput ?? io.stdin,
|
||||||
super(packagesDir, fileSystem, processRunner: processRunner) {
|
super(packagesDir, fileSystem,
|
||||||
|
processRunner: processRunner, gitDir: gitDir) {
|
||||||
argParser.addOption(
|
argParser.addOption(
|
||||||
_packageOption,
|
_packageOption,
|
||||||
help: 'The package to publish.'
|
help: 'The package to publish.'
|
||||||
@ -64,6 +68,22 @@ class PublishPluginCommand extends PluginCommand {
|
|||||||
// Flutter convention is to use "upstream" for the single source of truth, and "origin" for personal forks.
|
// Flutter convention is to use "upstream" for the single source of truth, and "origin" for personal forks.
|
||||||
defaultsTo: 'upstream',
|
defaultsTo: 'upstream',
|
||||||
);
|
);
|
||||||
|
argParser.addFlag(
|
||||||
|
_allChangedFlag,
|
||||||
|
help:
|
||||||
|
'Release all plugins that contains pubspec changes at the current commit compares to the base-sha.\n'
|
||||||
|
'The $_packageOption option is ignored if this is on.',
|
||||||
|
defaultsTo: false,
|
||||||
|
);
|
||||||
|
argParser.addFlag(
|
||||||
|
_dryRunFlag,
|
||||||
|
help:
|
||||||
|
'Skips the real `pub publish` and `git tag` commands and assumes both commands are successful.\n'
|
||||||
|
'This does not run `pub publish --dry-run`.\n'
|
||||||
|
'If you want to run the command with `pub publish --dry-run`, use `pub-publish-flags=--dry-run`',
|
||||||
|
defaultsTo: false,
|
||||||
|
negatable: true,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const String _packageOption = 'package';
|
static const String _packageOption = 'package';
|
||||||
@ -71,6 +91,8 @@ class PublishPluginCommand extends PluginCommand {
|
|||||||
static const String _pushTagsOption = 'push-tags';
|
static const String _pushTagsOption = 'push-tags';
|
||||||
static const String _pubFlagsOption = 'pub-publish-flags';
|
static const String _pubFlagsOption = 'pub-publish-flags';
|
||||||
static const String _remoteOption = 'remote';
|
static const String _remoteOption = 'remote';
|
||||||
|
static const String _allChangedFlag = 'all-changed';
|
||||||
|
static const String _dryRunFlag = 'dry-run';
|
||||||
|
|
||||||
// Version tags should follow <package-name>-v<semantic-version>. For example,
|
// Version tags should follow <package-name>-v<semantic-version>. For example,
|
||||||
// `flutter_plugin_tools-v0.0.24`.
|
// `flutter_plugin_tools-v0.0.24`.
|
||||||
@ -84,14 +106,14 @@ class PublishPluginCommand extends PluginCommand {
|
|||||||
'Attempts to publish the given plugin and tag its release on GitHub.';
|
'Attempts to publish the given plugin and tag its release on GitHub.';
|
||||||
|
|
||||||
final Print _print;
|
final Print _print;
|
||||||
final Stdin _stdin;
|
final io.Stdin _stdin;
|
||||||
// The directory of the actual package that we are publishing.
|
|
||||||
StreamSubscription<String> _stdinSubscription;
|
StreamSubscription<String> _stdinSubscription;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> run() async {
|
Future<void> run() async {
|
||||||
final String package = argResults[_packageOption] as String;
|
final String package = argResults[_packageOption] as String;
|
||||||
if (package == null) {
|
final bool publishAllChanged = argResults[_allChangedFlag] as bool;
|
||||||
|
if (package == null && !publishAllChanged) {
|
||||||
_print(
|
_print(
|
||||||
'Must specify a package to publish. See `plugin_tools help publish-plugin`.');
|
'Must specify a package to publish. See `plugin_tools help publish-plugin`.');
|
||||||
throw ToolExit(1);
|
throw ToolExit(1);
|
||||||
@ -102,6 +124,8 @@ class PublishPluginCommand extends PluginCommand {
|
|||||||
_print('$packagesDir is not a valid Git repository.');
|
_print('$packagesDir is not a valid Git repository.');
|
||||||
throw ToolExit(1);
|
throw ToolExit(1);
|
||||||
}
|
}
|
||||||
|
final GitDir baseGitDir =
|
||||||
|
await GitDir.fromExisting(packagesDir.path, allowSubdirectory: true);
|
||||||
|
|
||||||
final bool shouldPushTag = argResults[_pushTagsOption] == true;
|
final bool shouldPushTag = argResults[_pushTagsOption] == true;
|
||||||
final String remote = argResults[_remoteOption] as String;
|
final String remote = argResults[_remoteOption] as String;
|
||||||
@ -110,50 +134,229 @@ class PublishPluginCommand extends PluginCommand {
|
|||||||
remoteUrl = await _verifyRemote(remote);
|
remoteUrl = await _verifyRemote(remote);
|
||||||
}
|
}
|
||||||
_print('Local repo is ready!');
|
_print('Local repo is ready!');
|
||||||
|
if (argResults[_dryRunFlag] as bool) {
|
||||||
final Directory packageDir = _getPackageDir(package);
|
_print('=============== DRY RUN ===============');
|
||||||
await _publishPlugin(packageDir: packageDir);
|
|
||||||
if (argResults[_tagReleaseOption] as bool) {
|
|
||||||
await _tagRelease(
|
|
||||||
packageDir: packageDir,
|
|
||||||
remote: remote,
|
|
||||||
remoteUrl: remoteUrl,
|
|
||||||
shouldPushTag: shouldPushTag);
|
|
||||||
}
|
}
|
||||||
await _finishSuccesfully();
|
|
||||||
|
bool successful;
|
||||||
|
if (publishAllChanged) {
|
||||||
|
successful = await _publishAllChangedPackages(
|
||||||
|
remote: remote,
|
||||||
|
remoteUrl: remoteUrl,
|
||||||
|
shouldPushTag: shouldPushTag,
|
||||||
|
baseGitDir: baseGitDir,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
successful = await _publishAndTagPackage(
|
||||||
|
packageDir: _getPackageDir(package),
|
||||||
|
remote: remote,
|
||||||
|
remoteUrl: remoteUrl,
|
||||||
|
shouldPushTag: shouldPushTag,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
await _finish(successful);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _publishPlugin({@required Directory packageDir}) async {
|
Future<bool> _publishAllChangedPackages({
|
||||||
await _checkGitStatus(packageDir);
|
String remote,
|
||||||
await _publish(packageDir);
|
String remoteUrl,
|
||||||
|
bool shouldPushTag,
|
||||||
|
GitDir baseGitDir,
|
||||||
|
}) async {
|
||||||
|
final GitVersionFinder gitVersionFinder = await retrieveVersionFinder();
|
||||||
|
final List<String> changedPubspecs =
|
||||||
|
await gitVersionFinder.getChangedPubSpecs();
|
||||||
|
if (changedPubspecs.isEmpty) {
|
||||||
|
_print('No version updates in this commit.');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
_print('Getting existing tags...');
|
||||||
|
final io.ProcessResult existingTagsResult =
|
||||||
|
await baseGitDir.runCommand(<String>['tag', '--sort=-committerdate']);
|
||||||
|
final List<String> existingTags = (existingTagsResult.stdout as String)
|
||||||
|
.split('\n')
|
||||||
|
..removeWhere((String element) => element.isEmpty);
|
||||||
|
|
||||||
|
final List<String> packagesReleased = <String>[];
|
||||||
|
final List<String> packagesFailed = <String>[];
|
||||||
|
|
||||||
|
for (final String pubspecPath in changedPubspecs) {
|
||||||
|
final File pubspecFile =
|
||||||
|
fileSystem.directory(baseGitDir.path).childFile(pubspecPath);
|
||||||
|
final _CheckNeedsReleaseResult result = await _checkNeedsRelease(
|
||||||
|
pubspecFile: pubspecFile,
|
||||||
|
gitVersionFinder: gitVersionFinder,
|
||||||
|
existingTags: existingTags,
|
||||||
|
);
|
||||||
|
switch (result) {
|
||||||
|
case _CheckNeedsReleaseResult.release:
|
||||||
|
break;
|
||||||
|
case _CheckNeedsReleaseResult.noRelease:
|
||||||
|
continue;
|
||||||
|
case _CheckNeedsReleaseResult.failure:
|
||||||
|
packagesFailed.add(pubspecFile.parent.basename);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
_print('\n');
|
||||||
|
if (await _publishAndTagPackage(
|
||||||
|
packageDir: pubspecFile.parent,
|
||||||
|
remote: remote,
|
||||||
|
remoteUrl: remoteUrl,
|
||||||
|
shouldPushTag: shouldPushTag,
|
||||||
|
)) {
|
||||||
|
packagesReleased.add(pubspecFile.parent.basename);
|
||||||
|
} else {
|
||||||
|
packagesFailed.add(pubspecFile.parent.basename);
|
||||||
|
}
|
||||||
|
_print('\n');
|
||||||
|
}
|
||||||
|
if (packagesReleased.isNotEmpty) {
|
||||||
|
_print('Packages released: ${packagesReleased.join(', ')}');
|
||||||
|
}
|
||||||
|
if (packagesFailed.isNotEmpty) {
|
||||||
|
_print(
|
||||||
|
'Failed to release the following packages: ${packagesFailed.join(', ')}, see above for details.');
|
||||||
|
}
|
||||||
|
return packagesFailed.isEmpty;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Publish the package to pub with `pub publish`.
|
||||||
|
// If `_tagReleaseOption` is on, git tag the release.
|
||||||
|
// If `shouldPushTag` is `true`, the tag will be pushed to `remote`.
|
||||||
|
// Returns `true` if publishing and tag are successful.
|
||||||
|
Future<bool> _publishAndTagPackage({
|
||||||
|
@required Directory packageDir,
|
||||||
|
@required String remote,
|
||||||
|
@required String remoteUrl,
|
||||||
|
@required bool shouldPushTag,
|
||||||
|
}) async {
|
||||||
|
if (!await _publishPlugin(packageDir: packageDir)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (argResults[_tagReleaseOption] as bool) {
|
||||||
|
if (!await _tagRelease(
|
||||||
|
packageDir: packageDir,
|
||||||
|
remote: remote,
|
||||||
|
remoteUrl: remoteUrl,
|
||||||
|
shouldPushTag: shouldPushTag,
|
||||||
|
)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_print('Released [${packageDir.basename}] successfully.');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a [_CheckNeedsReleaseResult] that indicates the result.
|
||||||
|
Future<_CheckNeedsReleaseResult> _checkNeedsRelease({
|
||||||
|
@required File pubspecFile,
|
||||||
|
@required GitVersionFinder gitVersionFinder,
|
||||||
|
@required List<String> existingTags,
|
||||||
|
}) async {
|
||||||
|
if (!pubspecFile.existsSync()) {
|
||||||
|
_print('''
|
||||||
|
The file at The pubspec file at ${pubspecFile.path} does not exist. Publishing will not happen for ${pubspecFile.parent.basename}.
|
||||||
|
Safe to ignore if the package is deleted in this commit.
|
||||||
|
''');
|
||||||
|
return _CheckNeedsReleaseResult.noRelease;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Pubspec pubspec = Pubspec.parse(pubspecFile.readAsStringSync());
|
||||||
|
if (pubspec.publishTo == 'none') {
|
||||||
|
return _CheckNeedsReleaseResult.noRelease;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pubspec.version == null) {
|
||||||
|
_print('No version found. A package that intentionally has no version should be marked "publish_to: none"');
|
||||||
|
return _CheckNeedsReleaseResult.failure;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pubspec.name == null) {
|
||||||
|
_print('Fatal: Package name is null.');
|
||||||
|
return _CheckNeedsReleaseResult.failure;
|
||||||
|
}
|
||||||
|
// Get latest tagged version and compare with the current version.
|
||||||
|
// TODO(cyanglaz): Check latest version of the package on pub instead of git
|
||||||
|
// https://github.com/flutter/flutter/issues/81047
|
||||||
|
|
||||||
|
final String latestTag = existingTags.firstWhere(
|
||||||
|
(String tag) => tag.split('-v').first == pubspec.name,
|
||||||
|
orElse: () => '');
|
||||||
|
if (latestTag.isNotEmpty) {
|
||||||
|
final String latestTaggedVersion = latestTag.split('-v').last;
|
||||||
|
final Version latestVersion = Version.parse(latestTaggedVersion);
|
||||||
|
if (pubspec.version < latestVersion) {
|
||||||
|
_print(
|
||||||
|
'The new version (${pubspec.version}) is lower than the current version ($latestVersion) for ${pubspec.name}.\nThis git commit is a revert, no release is tagged.');
|
||||||
|
return _CheckNeedsReleaseResult.noRelease;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _CheckNeedsReleaseResult.release;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Publish the plugin.
|
||||||
|
//
|
||||||
|
// Returns `true` if successful, `false` otherwise.
|
||||||
|
Future<bool> _publishPlugin({@required Directory packageDir}) async {
|
||||||
|
final bool gitStatusOK = await _checkGitStatus(packageDir);
|
||||||
|
if (!gitStatusOK) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final bool publishOK = await _publish(packageDir);
|
||||||
|
if (!publishOK) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
_print('Package published!');
|
_print('Package published!');
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _tagRelease(
|
// Tag the release with <plugin-name>-v<version>
|
||||||
{@required Directory packageDir,
|
//
|
||||||
@required String remote,
|
// Return `true` if successful, `false` otherwise.
|
||||||
@required String remoteUrl,
|
Future<bool> _tagRelease({
|
||||||
@required bool shouldPushTag}) async {
|
@required Directory packageDir,
|
||||||
|
@required String remote,
|
||||||
|
@required String remoteUrl,
|
||||||
|
@required bool shouldPushTag,
|
||||||
|
}) async {
|
||||||
final String tag = _getTag(packageDir);
|
final String tag = _getTag(packageDir);
|
||||||
_print('Tagging release $tag...');
|
_print('Tagging release $tag...');
|
||||||
await processRunner.run(
|
if (!(argResults[_dryRunFlag] as bool)) {
|
||||||
'git',
|
final io.ProcessResult result = await processRunner.run(
|
||||||
<String>['tag', tag],
|
'git',
|
||||||
workingDir: packageDir,
|
<String>['tag', tag],
|
||||||
exitOnError: true,
|
workingDir: packageDir,
|
||||||
logOnError: true,
|
exitOnError: false,
|
||||||
);
|
logOnError: true,
|
||||||
|
);
|
||||||
|
if (result.exitCode != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!shouldPushTag) {
|
if (!shouldPushTag) {
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
_print('Pushing tag to $remote...');
|
_print('Pushing tag to $remote...');
|
||||||
await _pushTagToRemote(remote: remote, tag: tag, remoteUrl: remoteUrl);
|
return await _pushTagToRemote(
|
||||||
|
remote: remote,
|
||||||
|
tag: tag,
|
||||||
|
remoteUrl: remoteUrl,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _finishSuccesfully() async {
|
Future<void> _finish(bool successful) async {
|
||||||
await _stdinSubscription.cancel();
|
if (_stdinSubscription != null) {
|
||||||
_print('Done!');
|
await _stdinSubscription.cancel();
|
||||||
|
_stdinSubscription = null;
|
||||||
|
}
|
||||||
|
if (successful) {
|
||||||
|
_print('Done!');
|
||||||
|
} else {
|
||||||
|
_print('Failed, see above for details.');
|
||||||
|
throw ToolExit(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the packageDirectory based on the package name.
|
// Returns the packageDirectory based on the package name.
|
||||||
@ -167,14 +370,17 @@ class PublishPluginCommand extends PluginCommand {
|
|||||||
return packageDir;
|
return packageDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _checkGitStatus(Directory packageDir) async {
|
Future<bool> _checkGitStatus(Directory packageDir) async {
|
||||||
final ProcessResult statusResult = await processRunner.run(
|
final io.ProcessResult statusResult = await processRunner.run(
|
||||||
'git',
|
'git',
|
||||||
<String>['status', '--porcelain', '--ignored', packageDir.absolute.path],
|
<String>['status', '--porcelain', '--ignored', packageDir.absolute.path],
|
||||||
workingDir: packageDir,
|
workingDir: packageDir,
|
||||||
logOnError: true,
|
logOnError: true,
|
||||||
exitOnError: true,
|
exitOnError: false,
|
||||||
);
|
);
|
||||||
|
if (statusResult.exitCode != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
final String statusOutput = statusResult.stdout as String;
|
final String statusOutput = statusResult.stdout as String;
|
||||||
if (statusOutput.isNotEmpty) {
|
if (statusOutput.isNotEmpty) {
|
||||||
@ -182,12 +388,12 @@ class PublishPluginCommand extends PluginCommand {
|
|||||||
"There are files in the package directory that haven't been saved in git. Refusing to publish these files:\n\n"
|
"There are files in the package directory that haven't been saved in git. Refusing to publish these files:\n\n"
|
||||||
'$statusOutput\n'
|
'$statusOutput\n'
|
||||||
'If the directory should be clean, you can run `git clean -xdf && git reset --hard HEAD` to wipe all local changes.');
|
'If the directory should be clean, you can run `git clean -xdf && git reset --hard HEAD` to wipe all local changes.');
|
||||||
throw ToolExit(1);
|
|
||||||
}
|
}
|
||||||
|
return statusOutput.isEmpty;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String> _verifyRemote(String remote) async {
|
Future<String> _verifyRemote(String remote) async {
|
||||||
final ProcessResult remoteInfo = await processRunner.run(
|
final io.ProcessResult remoteInfo = await processRunner.run(
|
||||||
'git',
|
'git',
|
||||||
<String>['remote', 'get-url', remote],
|
<String>['remote', 'get-url', remote],
|
||||||
workingDir: packagesDir,
|
workingDir: packagesDir,
|
||||||
@ -197,28 +403,31 @@ class PublishPluginCommand extends PluginCommand {
|
|||||||
return remoteInfo.stdout as String;
|
return remoteInfo.stdout as String;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _publish(Directory packageDir) async {
|
Future<bool> _publish(Directory packageDir) async {
|
||||||
final List<String> publishFlags =
|
final List<String> publishFlags =
|
||||||
argResults[_pubFlagsOption] as List<String>;
|
argResults[_pubFlagsOption] as List<String>;
|
||||||
_print(
|
_print(
|
||||||
'Running `pub publish ${publishFlags.join(' ')}` in ${packageDir.absolute.path}...\n');
|
'Running `pub publish ${publishFlags.join(' ')}` in ${packageDir.absolute.path}...\n');
|
||||||
final Process publish = await processRunner.start(
|
if (!(argResults[_dryRunFlag] as bool)) {
|
||||||
'flutter', <String>['pub', 'publish'] + publishFlags,
|
final io.Process publish = await processRunner.start(
|
||||||
workingDirectory: packageDir);
|
'flutter', <String>['pub', 'publish'] + publishFlags,
|
||||||
publish.stdout
|
workingDirectory: packageDir);
|
||||||
.transform(utf8.decoder)
|
publish.stdout
|
||||||
.listen((String data) => _print(data));
|
.transform(utf8.decoder)
|
||||||
publish.stderr
|
.listen((String data) => _print(data));
|
||||||
.transform(utf8.decoder)
|
publish.stderr
|
||||||
.listen((String data) => _print(data));
|
.transform(utf8.decoder)
|
||||||
_stdinSubscription = _stdin
|
.listen((String data) => _print(data));
|
||||||
.transform(utf8.decoder)
|
_stdinSubscription ??= _stdin
|
||||||
.listen((String data) => publish.stdin.writeln(data));
|
.transform(utf8.decoder)
|
||||||
final int result = await publish.exitCode;
|
.listen((String data) => publish.stdin.writeln(data));
|
||||||
if (result != 0) {
|
final int result = await publish.exitCode;
|
||||||
_print('Publish failed. Exiting.');
|
if (result != 0) {
|
||||||
throw ToolExit(result);
|
_print('Publish ${packageDir.basename} failed.');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
String _getTag(Directory packageDir) {
|
String _getTag(Directory packageDir) {
|
||||||
@ -235,23 +444,44 @@ class PublishPluginCommand extends PluginCommand {
|
|||||||
.replaceAll('%VERSION%', version);
|
.replaceAll('%VERSION%', version);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _pushTagToRemote(
|
// Pushes the `tag` to `remote`
|
||||||
{@required String remote,
|
//
|
||||||
@required String tag,
|
// Return `true` if successful, `false` otherwise.
|
||||||
@required String remoteUrl}) async {
|
Future<bool> _pushTagToRemote({
|
||||||
|
@required String remote,
|
||||||
|
@required String tag,
|
||||||
|
@required String remoteUrl,
|
||||||
|
}) async {
|
||||||
assert(remote != null && tag != null && remoteUrl != null);
|
assert(remote != null && tag != null && remoteUrl != null);
|
||||||
_print('Ready to push $tag to $remoteUrl (y/n)?');
|
_print('Ready to push $tag to $remoteUrl (y/n)?');
|
||||||
final String input = _stdin.readLineSync();
|
final String input = _stdin.readLineSync();
|
||||||
if (input.toLowerCase() != 'y') {
|
if (input.toLowerCase() != 'y') {
|
||||||
_print('Tag push canceled.');
|
_print('Tag push canceled.');
|
||||||
throw ToolExit(1);
|
return false;
|
||||||
}
|
}
|
||||||
await processRunner.run(
|
if (!(argResults[_dryRunFlag] as bool)) {
|
||||||
'git',
|
final io.ProcessResult result = await processRunner.run(
|
||||||
<String>['push', remote, tag],
|
'git',
|
||||||
workingDir: packagesDir,
|
<String>['push', remote, tag],
|
||||||
exitOnError: true,
|
workingDir: packagesDir,
|
||||||
logOnError: true,
|
exitOnError: false,
|
||||||
);
|
logOnError: true,
|
||||||
|
);
|
||||||
|
if (result.exitCode != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum _CheckNeedsReleaseResult {
|
||||||
|
// The package needs to be released.
|
||||||
|
release,
|
||||||
|
|
||||||
|
// The package does not need to be released.
|
||||||
|
noRelease,
|
||||||
|
|
||||||
|
// There's an error when trying to determine whether the package needs to be released.
|
||||||
|
failure,
|
||||||
|
}
|
||||||
|
@ -53,7 +53,8 @@ void main() {
|
|||||||
mockPackagesDir, mockPackagesDir.fileSystem,
|
mockPackagesDir, mockPackagesDir.fileSystem,
|
||||||
processRunner: processRunner,
|
processRunner: processRunner,
|
||||||
print: (Object message) => printedMessages.add(message.toString()),
|
print: (Object message) => printedMessages.add(message.toString()),
|
||||||
stdinput: mockStdin));
|
stdinput: mockStdin,
|
||||||
|
gitDir: await GitDir.fromExisting(mockPackagesDir.path)));
|
||||||
});
|
});
|
||||||
|
|
||||||
tearDown(() {
|
tearDown(() {
|
||||||
@ -95,9 +96,11 @@ void main() {
|
|||||||
throwsA(const TypeMatcher<ToolExit>()));
|
throwsA(const TypeMatcher<ToolExit>()));
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
printedMessages.last,
|
printedMessages,
|
||||||
contains(
|
containsAllInOrder(<String>[
|
||||||
"There are files in the package directory that haven't been saved in git."));
|
'There are files in the package directory that haven\'t been saved in git. Refusing to publish these files:\n\n?? foo/tmp\n\nIf the directory should be clean, you can run `git clean -xdf && git reset --hard HEAD` to wipe all local changes.',
|
||||||
|
'Failed, see above for details.',
|
||||||
|
]));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('fails immediately if the remote doesn\'t exist', () async {
|
test('fails immediately if the remote doesn\'t exist', () async {
|
||||||
@ -110,7 +113,7 @@ void main() {
|
|||||||
|
|
||||||
test("doesn't validate the remote if it's not pushing tags", () async {
|
test("doesn't validate the remote if it's not pushing tags", () async {
|
||||||
// Immediately return 0 when running `pub publish`.
|
// Immediately return 0 when running `pub publish`.
|
||||||
processRunner.mockPublishProcess.exitCodeCompleter.complete(0);
|
processRunner.mockPublishCompleteCode = 0;
|
||||||
|
|
||||||
await commandRunner.run(<String>[
|
await commandRunner.run(<String>[
|
||||||
'publish-plugin',
|
'publish-plugin',
|
||||||
@ -131,7 +134,7 @@ void main() {
|
|||||||
await gitDir.runCommand(<String>['add', '-A']);
|
await gitDir.runCommand(<String>['add', '-A']);
|
||||||
await gitDir.runCommand(<String>['commit', '-m', 'Initial commit']);
|
await gitDir.runCommand(<String>['commit', '-m', 'Initial commit']);
|
||||||
// Immediately return 0 when running `pub publish`.
|
// Immediately return 0 when running `pub publish`.
|
||||||
processRunner.mockPublishProcess.exitCodeCompleter.complete(0);
|
processRunner.mockPublishCompleteCode = 0;
|
||||||
await commandRunner.run(<String>[
|
await commandRunner.run(<String>[
|
||||||
'publish-plugin',
|
'publish-plugin',
|
||||||
'--package',
|
'--package',
|
||||||
@ -152,9 +155,10 @@ void main() {
|
|||||||
'--no-push-tags',
|
'--no-push-tags',
|
||||||
'--no-tag-release'
|
'--no-tag-release'
|
||||||
]);
|
]);
|
||||||
processRunner.mockPublishProcess.stdoutController.add(utf8.encode('Foo'));
|
|
||||||
processRunner.mockPublishProcess.stderrController.add(utf8.encode('Bar'));
|
processRunner.mockPublishStdout = 'Foo';
|
||||||
processRunner.mockPublishProcess.exitCodeCompleter.complete(0);
|
processRunner.mockPublishStderr = 'Bar';
|
||||||
|
processRunner.mockPublishCompleteCode = 0;
|
||||||
|
|
||||||
await publishCommand;
|
await publishCommand;
|
||||||
|
|
||||||
@ -170,8 +174,8 @@ void main() {
|
|||||||
'--no-push-tags',
|
'--no-push-tags',
|
||||||
'--no-tag-release'
|
'--no-tag-release'
|
||||||
]);
|
]);
|
||||||
mockStdin.controller.add(utf8.encode('user input'));
|
mockStdin.mockUserInputs.add(utf8.encode('user input'));
|
||||||
processRunner.mockPublishProcess.exitCodeCompleter.complete(0);
|
processRunner.mockPublishCompleteCode = 0;
|
||||||
|
|
||||||
await publishCommand;
|
await publishCommand;
|
||||||
|
|
||||||
@ -180,7 +184,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('forwards --pub-publish-flags to pub publish', () async {
|
test('forwards --pub-publish-flags to pub publish', () async {
|
||||||
processRunner.mockPublishProcess.exitCodeCompleter.complete(0);
|
processRunner.mockPublishCompleteCode = 0;
|
||||||
await commandRunner.run(<String>[
|
await commandRunner.run(<String>[
|
||||||
'publish-plugin',
|
'publish-plugin',
|
||||||
'--package',
|
'--package',
|
||||||
@ -199,7 +203,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('throws if pub publish fails', () async {
|
test('throws if pub publish fails', () async {
|
||||||
processRunner.mockPublishProcess.exitCodeCompleter.complete(128);
|
processRunner.mockPublishCompleteCode = 128;
|
||||||
await expectLater(
|
await expectLater(
|
||||||
() => commandRunner.run(<String>[
|
() => commandRunner.run(<String>[
|
||||||
'publish-plugin',
|
'publish-plugin',
|
||||||
@ -210,13 +214,35 @@ void main() {
|
|||||||
]),
|
]),
|
||||||
throwsA(const TypeMatcher<ToolExit>()));
|
throwsA(const TypeMatcher<ToolExit>()));
|
||||||
|
|
||||||
expect(printedMessages, contains('Publish failed. Exiting.'));
|
expect(printedMessages, contains('Publish foo failed.'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('publish, dry run', () async {
|
||||||
|
// Immediately return 1 when running `pub publish`. If dry-run does not work, test should throw.
|
||||||
|
processRunner.mockPublishCompleteCode = 1;
|
||||||
|
await commandRunner.run(<String>[
|
||||||
|
'publish-plugin',
|
||||||
|
'--package',
|
||||||
|
testPluginName,
|
||||||
|
'--dry-run',
|
||||||
|
'--no-push-tags',
|
||||||
|
'--no-tag-release',
|
||||||
|
]);
|
||||||
|
|
||||||
|
expect(processRunner.pushTagsArgs, isEmpty);
|
||||||
|
expect(
|
||||||
|
printedMessages,
|
||||||
|
containsAllInOrder(<String>[
|
||||||
|
'=============== DRY RUN ===============',
|
||||||
|
'Running `pub publish ` in ${pluginDir.path}...\n',
|
||||||
|
'Done!'
|
||||||
|
]));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
group('Tags release', () {
|
group('Tags release', () {
|
||||||
test('with the version and name from the pubspec.yaml', () async {
|
test('with the version and name from the pubspec.yaml', () async {
|
||||||
processRunner.mockPublishProcess.exitCodeCompleter.complete(0);
|
processRunner.mockPublishCompleteCode = 0;
|
||||||
await commandRunner.run(<String>[
|
await commandRunner.run(<String>[
|
||||||
'publish-plugin',
|
'publish-plugin',
|
||||||
'--package',
|
'--package',
|
||||||
@ -231,7 +257,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('only if publishing succeeded', () async {
|
test('only if publishing succeeded', () async {
|
||||||
processRunner.mockPublishProcess.exitCodeCompleter.complete(128);
|
processRunner.mockPublishCompleteCode = 128;
|
||||||
await expectLater(
|
await expectLater(
|
||||||
() => commandRunner.run(<String>[
|
() => commandRunner.run(<String>[
|
||||||
'publish-plugin',
|
'publish-plugin',
|
||||||
@ -241,7 +267,7 @@ void main() {
|
|||||||
]),
|
]),
|
||||||
throwsA(const TypeMatcher<ToolExit>()));
|
throwsA(const TypeMatcher<ToolExit>()));
|
||||||
|
|
||||||
expect(printedMessages, contains('Publish failed. Exiting.'));
|
expect(printedMessages, contains('Publish foo failed.'));
|
||||||
final String tag = (await gitDir.runCommand(
|
final String tag = (await gitDir.runCommand(
|
||||||
<String>['show-ref', 'fake_package-v0.0.1'],
|
<String>['show-ref', 'fake_package-v0.0.1'],
|
||||||
throwOnError: false))
|
throwOnError: false))
|
||||||
@ -257,7 +283,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('requires user confirmation', () async {
|
test('requires user confirmation', () async {
|
||||||
processRunner.mockPublishProcess.exitCodeCompleter.complete(0);
|
processRunner.mockPublishCompleteCode = 0;
|
||||||
mockStdin.readLineOutput = 'help';
|
mockStdin.readLineOutput = 'help';
|
||||||
await expectLater(
|
await expectLater(
|
||||||
() => commandRunner.run(<String>[
|
() => commandRunner.run(<String>[
|
||||||
@ -272,7 +298,7 @@ void main() {
|
|||||||
|
|
||||||
test('to upstream by default', () async {
|
test('to upstream by default', () async {
|
||||||
await gitDir.runCommand(<String>['tag', 'garbage']);
|
await gitDir.runCommand(<String>['tag', 'garbage']);
|
||||||
processRunner.mockPublishProcess.exitCodeCompleter.complete(0);
|
processRunner.mockPublishCompleteCode = 0;
|
||||||
mockStdin.readLineOutput = 'y';
|
mockStdin.readLineOutput = 'y';
|
||||||
await commandRunner.run(<String>[
|
await commandRunner.run(<String>[
|
||||||
'publish-plugin',
|
'publish-plugin',
|
||||||
@ -286,10 +312,30 @@ void main() {
|
|||||||
expect(printedMessages.last, 'Done!');
|
expect(printedMessages.last, 'Done!');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('to upstream by default, dry run', () async {
|
||||||
|
await gitDir.runCommand(<String>['tag', 'garbage']);
|
||||||
|
// Immediately return 1 when running `pub publish`. If dry-run does not work, test should throw.
|
||||||
|
processRunner.mockPublishCompleteCode = 1;
|
||||||
|
mockStdin.readLineOutput = 'y';
|
||||||
|
await commandRunner.run(
|
||||||
|
<String>['publish-plugin', '--package', testPluginName, '--dry-run']);
|
||||||
|
|
||||||
|
expect(processRunner.pushTagsArgs, isEmpty);
|
||||||
|
expect(
|
||||||
|
printedMessages,
|
||||||
|
containsAllInOrder(<String>[
|
||||||
|
'=============== DRY RUN ===============',
|
||||||
|
'Running `pub publish ` in ${pluginDir.path}...\n',
|
||||||
|
'Tagging release fake_package-v0.0.1...',
|
||||||
|
'Pushing tag to upstream...',
|
||||||
|
'Done!'
|
||||||
|
]));
|
||||||
|
});
|
||||||
|
|
||||||
test('to different remotes based on a flag', () async {
|
test('to different remotes based on a flag', () async {
|
||||||
await gitDir.runCommand(
|
await gitDir.runCommand(
|
||||||
<String>['remote', 'add', 'origin', 'http://localhost:8001']);
|
<String>['remote', 'add', 'origin', 'http://localhost:8001']);
|
||||||
processRunner.mockPublishProcess.exitCodeCompleter.complete(0);
|
processRunner.mockPublishCompleteCode = 0;
|
||||||
mockStdin.readLineOutput = 'y';
|
mockStdin.readLineOutput = 'y';
|
||||||
await commandRunner.run(<String>[
|
await commandRunner.run(<String>[
|
||||||
'publish-plugin',
|
'publish-plugin',
|
||||||
@ -306,7 +352,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('only if tagging and pushing to remotes are both enabled', () async {
|
test('only if tagging and pushing to remotes are both enabled', () async {
|
||||||
processRunner.mockPublishProcess.exitCodeCompleter.complete(0);
|
processRunner.mockPublishCompleteCode = 0;
|
||||||
await commandRunner.run(<String>[
|
await commandRunner.run(<String>[
|
||||||
'publish-plugin',
|
'publish-plugin',
|
||||||
'--package',
|
'--package',
|
||||||
@ -318,15 +364,495 @@ void main() {
|
|||||||
expect(printedMessages.last, 'Done!');
|
expect(printedMessages.last, 'Done!');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
group('Auto release (all-changed flag)', () {
|
||||||
|
setUp(() async {
|
||||||
|
io.Process.runSync('git', <String>['init'],
|
||||||
|
workingDirectory: mockPackagesDir.path);
|
||||||
|
gitDir = await GitDir.fromExisting(mockPackagesDir.path);
|
||||||
|
await gitDir.runCommand(
|
||||||
|
<String>['remote', 'add', 'upstream', 'http://localhost:8000']);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('can release newly created plugins', () async {
|
||||||
|
// Non-federated
|
||||||
|
final Directory pluginDir1 = createFakePlugin('plugin1',
|
||||||
|
withSingleExample: true, packagesDirectory: mockPackagesDir);
|
||||||
|
// federated
|
||||||
|
final Directory pluginDir2 = createFakePlugin('plugin2',
|
||||||
|
withSingleExample: true,
|
||||||
|
parentDirectoryName: 'plugin2',
|
||||||
|
packagesDirectory: mockPackagesDir);
|
||||||
|
createFakePubspec(pluginDir1,
|
||||||
|
name: 'plugin1',
|
||||||
|
includeVersion: true,
|
||||||
|
isFlutter: false,
|
||||||
|
version: '0.0.1');
|
||||||
|
createFakePubspec(pluginDir2,
|
||||||
|
name: 'plugin2',
|
||||||
|
includeVersion: true,
|
||||||
|
isFlutter: false,
|
||||||
|
version: '0.0.1');
|
||||||
|
await gitDir.runCommand(<String>['add', '-A']);
|
||||||
|
await gitDir.runCommand(<String>['commit', '-m', 'Add plugins']);
|
||||||
|
// Immediately return 0 when running `pub publish`.
|
||||||
|
processRunner.mockPublishCompleteCode = 0;
|
||||||
|
mockStdin.readLineOutput = 'y';
|
||||||
|
await commandRunner
|
||||||
|
.run(<String>['publish-plugin', '--all-changed', '--base-sha=HEAD~']);
|
||||||
|
expect(
|
||||||
|
printedMessages,
|
||||||
|
containsAllInOrder(<String>[
|
||||||
|
'Checking local repo...',
|
||||||
|
'Local repo is ready!',
|
||||||
|
'Getting existing tags...',
|
||||||
|
'Running `pub publish ` in ${pluginDir1.path}...\n',
|
||||||
|
'Running `pub publish ` in ${pluginDir2.path}...\n',
|
||||||
|
'Packages released: plugin1, plugin2',
|
||||||
|
'Done!'
|
||||||
|
]));
|
||||||
|
expect(processRunner.pushTagsArgs, isNotEmpty);
|
||||||
|
expect(processRunner.pushTagsArgs[0], 'push');
|
||||||
|
expect(processRunner.pushTagsArgs[1], 'upstream');
|
||||||
|
expect(processRunner.pushTagsArgs[2], 'plugin1-v0.0.1');
|
||||||
|
expect(processRunner.pushTagsArgs[3], 'push');
|
||||||
|
expect(processRunner.pushTagsArgs[4], 'upstream');
|
||||||
|
expect(processRunner.pushTagsArgs[5], 'plugin2-v0.0.1');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('can release newly created plugins, while there are existing plugins',
|
||||||
|
() async {
|
||||||
|
// Prepare an exiting plugin and tag it
|
||||||
|
final Directory pluginDir0 = createFakePlugin('plugin0',
|
||||||
|
withSingleExample: true, packagesDirectory: mockPackagesDir);
|
||||||
|
createFakePubspec(pluginDir0,
|
||||||
|
name: 'plugin0',
|
||||||
|
includeVersion: true,
|
||||||
|
isFlutter: false,
|
||||||
|
version: '0.0.1');
|
||||||
|
await gitDir.runCommand(<String>['add', '-A']);
|
||||||
|
await gitDir.runCommand(<String>['commit', '-m', 'Add plugins']);
|
||||||
|
// Immediately return 0 when running `pub publish`.
|
||||||
|
processRunner.mockPublishCompleteCode = 0;
|
||||||
|
mockStdin.readLineOutput = 'y';
|
||||||
|
await commandRunner
|
||||||
|
.run(<String>['publish-plugin', '--all-changed', '--base-sha=HEAD~']);
|
||||||
|
processRunner.pushTagsArgs.clear();
|
||||||
|
|
||||||
|
// Non-federated
|
||||||
|
final Directory pluginDir1 = createFakePlugin('plugin1',
|
||||||
|
withSingleExample: true, packagesDirectory: mockPackagesDir);
|
||||||
|
// federated
|
||||||
|
final Directory pluginDir2 = createFakePlugin('plugin2',
|
||||||
|
withSingleExample: true,
|
||||||
|
parentDirectoryName: 'plugin2',
|
||||||
|
packagesDirectory: mockPackagesDir);
|
||||||
|
createFakePubspec(pluginDir1,
|
||||||
|
name: 'plugin1',
|
||||||
|
includeVersion: true,
|
||||||
|
isFlutter: false,
|
||||||
|
version: '0.0.1');
|
||||||
|
createFakePubspec(pluginDir2,
|
||||||
|
name: 'plugin2',
|
||||||
|
includeVersion: true,
|
||||||
|
isFlutter: false,
|
||||||
|
version: '0.0.1');
|
||||||
|
await gitDir.runCommand(<String>['add', '-A']);
|
||||||
|
await gitDir.runCommand(<String>['commit', '-m', 'Add plugins']);
|
||||||
|
// Immediately return 0 when running `pub publish`.
|
||||||
|
await commandRunner
|
||||||
|
.run(<String>['publish-plugin', '--all-changed', '--base-sha=HEAD~']);
|
||||||
|
expect(
|
||||||
|
printedMessages,
|
||||||
|
containsAllInOrder(<String>[
|
||||||
|
'Checking local repo...',
|
||||||
|
'Local repo is ready!',
|
||||||
|
'Getting existing tags...',
|
||||||
|
'Running `pub publish ` in ${pluginDir1.path}...\n',
|
||||||
|
'Running `pub publish ` in ${pluginDir2.path}...\n',
|
||||||
|
'Packages released: plugin1, plugin2',
|
||||||
|
'Done!'
|
||||||
|
]));
|
||||||
|
expect(processRunner.pushTagsArgs, isNotEmpty);
|
||||||
|
expect(processRunner.pushTagsArgs[0], 'push');
|
||||||
|
expect(processRunner.pushTagsArgs[1], 'upstream');
|
||||||
|
expect(processRunner.pushTagsArgs[2], 'plugin1-v0.0.1');
|
||||||
|
expect(processRunner.pushTagsArgs[3], 'push');
|
||||||
|
expect(processRunner.pushTagsArgs[4], 'upstream');
|
||||||
|
expect(processRunner.pushTagsArgs[5], 'plugin2-v0.0.1');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('can release newly created plugins, dry run', () async {
|
||||||
|
// Non-federated
|
||||||
|
final Directory pluginDir1 = createFakePlugin('plugin1',
|
||||||
|
withSingleExample: true, packagesDirectory: mockPackagesDir);
|
||||||
|
// federated
|
||||||
|
final Directory pluginDir2 = createFakePlugin('plugin2',
|
||||||
|
withSingleExample: true,
|
||||||
|
parentDirectoryName: 'plugin2',
|
||||||
|
packagesDirectory: mockPackagesDir);
|
||||||
|
createFakePubspec(pluginDir1,
|
||||||
|
name: 'plugin1',
|
||||||
|
includeVersion: true,
|
||||||
|
isFlutter: false,
|
||||||
|
version: '0.0.1');
|
||||||
|
createFakePubspec(pluginDir2,
|
||||||
|
name: 'plugin2',
|
||||||
|
includeVersion: true,
|
||||||
|
isFlutter: false,
|
||||||
|
version: '0.0.1');
|
||||||
|
await gitDir.runCommand(<String>['add', '-A']);
|
||||||
|
await gitDir.runCommand(<String>['commit', '-m', 'Add plugins']);
|
||||||
|
// Immediately return 1 when running `pub publish`. If dry-run does not work, test should throw.
|
||||||
|
processRunner.mockPublishCompleteCode = 1;
|
||||||
|
mockStdin.readLineOutput = 'y';
|
||||||
|
await commandRunner.run(<String>[
|
||||||
|
'publish-plugin',
|
||||||
|
'--all-changed',
|
||||||
|
'--base-sha=HEAD~',
|
||||||
|
'--dry-run'
|
||||||
|
]);
|
||||||
|
expect(
|
||||||
|
printedMessages,
|
||||||
|
containsAllInOrder(<String>[
|
||||||
|
'Checking local repo...',
|
||||||
|
'Local repo is ready!',
|
||||||
|
'=============== DRY RUN ===============',
|
||||||
|
'Getting existing tags...',
|
||||||
|
'Running `pub publish ` in ${pluginDir1.path}...\n',
|
||||||
|
'Tagging release plugin1-v0.0.1...',
|
||||||
|
'Pushing tag to upstream...',
|
||||||
|
'Running `pub publish ` in ${pluginDir2.path}...\n',
|
||||||
|
'Tagging release plugin2-v0.0.1...',
|
||||||
|
'Pushing tag to upstream...',
|
||||||
|
'Packages released: plugin1, plugin2',
|
||||||
|
'Done!'
|
||||||
|
]));
|
||||||
|
expect(processRunner.pushTagsArgs, isEmpty);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('version change triggers releases.', () async {
|
||||||
|
// Non-federated
|
||||||
|
final Directory pluginDir1 = createFakePlugin('plugin1',
|
||||||
|
withSingleExample: true, packagesDirectory: mockPackagesDir);
|
||||||
|
// federated
|
||||||
|
final Directory pluginDir2 = createFakePlugin('plugin2',
|
||||||
|
withSingleExample: true,
|
||||||
|
parentDirectoryName: 'plugin2',
|
||||||
|
packagesDirectory: mockPackagesDir);
|
||||||
|
createFakePubspec(pluginDir1,
|
||||||
|
name: 'plugin1',
|
||||||
|
includeVersion: true,
|
||||||
|
isFlutter: false,
|
||||||
|
version: '0.0.1');
|
||||||
|
createFakePubspec(pluginDir2,
|
||||||
|
name: 'plugin2',
|
||||||
|
includeVersion: true,
|
||||||
|
isFlutter: false,
|
||||||
|
version: '0.0.1');
|
||||||
|
await gitDir.runCommand(<String>['add', '-A']);
|
||||||
|
await gitDir.runCommand(<String>['commit', '-m', 'Add plugins']);
|
||||||
|
// Immediately return 0 when running `pub publish`.
|
||||||
|
processRunner.mockPublishCompleteCode = 0;
|
||||||
|
mockStdin.readLineOutput = 'y';
|
||||||
|
await commandRunner
|
||||||
|
.run(<String>['publish-plugin', '--all-changed', '--base-sha=HEAD~']);
|
||||||
|
expect(
|
||||||
|
printedMessages,
|
||||||
|
containsAllInOrder(<String>[
|
||||||
|
'Checking local repo...',
|
||||||
|
'Local repo is ready!',
|
||||||
|
'Getting existing tags...',
|
||||||
|
'Running `pub publish ` in ${pluginDir1.path}...\n',
|
||||||
|
'Running `pub publish ` in ${pluginDir2.path}...\n',
|
||||||
|
'Packages released: plugin1, plugin2',
|
||||||
|
'Done!'
|
||||||
|
]));
|
||||||
|
expect(processRunner.pushTagsArgs, isNotEmpty);
|
||||||
|
expect(processRunner.pushTagsArgs[0], 'push');
|
||||||
|
expect(processRunner.pushTagsArgs[1], 'upstream');
|
||||||
|
expect(processRunner.pushTagsArgs[2], 'plugin1-v0.0.1');
|
||||||
|
expect(processRunner.pushTagsArgs[3], 'push');
|
||||||
|
expect(processRunner.pushTagsArgs[4], 'upstream');
|
||||||
|
expect(processRunner.pushTagsArgs[5], 'plugin2-v0.0.1');
|
||||||
|
|
||||||
|
processRunner.pushTagsArgs.clear();
|
||||||
|
printedMessages.clear();
|
||||||
|
|
||||||
|
final List<String> plugin1Pubspec =
|
||||||
|
pluginDir1.childFile('pubspec.yaml').readAsLinesSync();
|
||||||
|
plugin1Pubspec[plugin1Pubspec.indexWhere(
|
||||||
|
(String element) => element.contains('version:'))] = 'version: 0.0.2';
|
||||||
|
pluginDir1
|
||||||
|
.childFile('pubspec.yaml')
|
||||||
|
.writeAsStringSync(plugin1Pubspec.join('\n'));
|
||||||
|
final List<String> plugin2Pubspec =
|
||||||
|
pluginDir2.childFile('pubspec.yaml').readAsLinesSync();
|
||||||
|
plugin2Pubspec[plugin2Pubspec.indexWhere(
|
||||||
|
(String element) => element.contains('version:'))] = 'version: 0.0.2';
|
||||||
|
pluginDir2
|
||||||
|
.childFile('pubspec.yaml')
|
||||||
|
.writeAsStringSync(plugin2Pubspec.join('\n'));
|
||||||
|
await gitDir.runCommand(<String>['add', '-A']);
|
||||||
|
await gitDir
|
||||||
|
.runCommand(<String>['commit', '-m', 'Update versions to 0.0.2']);
|
||||||
|
|
||||||
|
await commandRunner
|
||||||
|
.run(<String>['publish-plugin', '--all-changed', '--base-sha=HEAD~']);
|
||||||
|
expect(
|
||||||
|
printedMessages,
|
||||||
|
containsAllInOrder(<String>[
|
||||||
|
'Checking local repo...',
|
||||||
|
'Local repo is ready!',
|
||||||
|
'Getting existing tags...',
|
||||||
|
'Running `pub publish ` in ${pluginDir1.path}...\n',
|
||||||
|
'Running `pub publish ` in ${pluginDir2.path}...\n',
|
||||||
|
'Packages released: plugin1, plugin2',
|
||||||
|
'Done!'
|
||||||
|
]));
|
||||||
|
|
||||||
|
expect(processRunner.pushTagsArgs, isNotEmpty);
|
||||||
|
expect(processRunner.pushTagsArgs[0], 'push');
|
||||||
|
expect(processRunner.pushTagsArgs[1], 'upstream');
|
||||||
|
expect(processRunner.pushTagsArgs[2], 'plugin1-v0.0.2');
|
||||||
|
expect(processRunner.pushTagsArgs[3], 'push');
|
||||||
|
expect(processRunner.pushTagsArgs[4], 'upstream');
|
||||||
|
expect(processRunner.pushTagsArgs[5], 'plugin2-v0.0.2');
|
||||||
|
});
|
||||||
|
|
||||||
|
test(
|
||||||
|
'delete package will not trigger publish but exit the command successfully.',
|
||||||
|
() async {
|
||||||
|
// Non-federated
|
||||||
|
final Directory pluginDir1 = createFakePlugin('plugin1',
|
||||||
|
withSingleExample: true, packagesDirectory: mockPackagesDir);
|
||||||
|
// federated
|
||||||
|
final Directory pluginDir2 = createFakePlugin('plugin2',
|
||||||
|
withSingleExample: true,
|
||||||
|
parentDirectoryName: 'plugin2',
|
||||||
|
packagesDirectory: mockPackagesDir);
|
||||||
|
createFakePubspec(pluginDir1,
|
||||||
|
name: 'plugin1',
|
||||||
|
includeVersion: true,
|
||||||
|
isFlutter: false,
|
||||||
|
version: '0.0.1');
|
||||||
|
createFakePubspec(pluginDir2,
|
||||||
|
name: 'plugin2',
|
||||||
|
includeVersion: true,
|
||||||
|
isFlutter: false,
|
||||||
|
version: '0.0.1');
|
||||||
|
await gitDir.runCommand(<String>['add', '-A']);
|
||||||
|
await gitDir.runCommand(<String>['commit', '-m', 'Add plugins']);
|
||||||
|
// Immediately return 0 when running `pub publish`.
|
||||||
|
processRunner.mockPublishCompleteCode = 0;
|
||||||
|
mockStdin.readLineOutput = 'y';
|
||||||
|
await commandRunner
|
||||||
|
.run(<String>['publish-plugin', '--all-changed', '--base-sha=HEAD~']);
|
||||||
|
expect(
|
||||||
|
printedMessages,
|
||||||
|
containsAllInOrder(<String>[
|
||||||
|
'Checking local repo...',
|
||||||
|
'Local repo is ready!',
|
||||||
|
'Getting existing tags...',
|
||||||
|
'Running `pub publish ` in ${pluginDir1.path}...\n',
|
||||||
|
'Running `pub publish ` in ${pluginDir2.path}...\n',
|
||||||
|
'Packages released: plugin1, plugin2',
|
||||||
|
'Done!'
|
||||||
|
]));
|
||||||
|
expect(processRunner.pushTagsArgs, isNotEmpty);
|
||||||
|
expect(processRunner.pushTagsArgs[0], 'push');
|
||||||
|
expect(processRunner.pushTagsArgs[1], 'upstream');
|
||||||
|
expect(processRunner.pushTagsArgs[2], 'plugin1-v0.0.1');
|
||||||
|
expect(processRunner.pushTagsArgs[3], 'push');
|
||||||
|
expect(processRunner.pushTagsArgs[4], 'upstream');
|
||||||
|
expect(processRunner.pushTagsArgs[5], 'plugin2-v0.0.1');
|
||||||
|
|
||||||
|
processRunner.pushTagsArgs.clear();
|
||||||
|
printedMessages.clear();
|
||||||
|
|
||||||
|
final List<String> plugin1Pubspec =
|
||||||
|
pluginDir1.childFile('pubspec.yaml').readAsLinesSync();
|
||||||
|
plugin1Pubspec[plugin1Pubspec.indexWhere(
|
||||||
|
(String element) => element.contains('version:'))] = 'version: 0.0.2';
|
||||||
|
pluginDir1
|
||||||
|
.childFile('pubspec.yaml')
|
||||||
|
.writeAsStringSync(plugin1Pubspec.join('\n'));
|
||||||
|
|
||||||
|
pluginDir2.deleteSync(recursive: true);
|
||||||
|
|
||||||
|
await gitDir.runCommand(<String>['add', '-A']);
|
||||||
|
await gitDir.runCommand(<String>[
|
||||||
|
'commit',
|
||||||
|
'-m',
|
||||||
|
'Update plugin1 versions to 0.0.2, delete plugin2'
|
||||||
|
]);
|
||||||
|
|
||||||
|
await commandRunner
|
||||||
|
.run(<String>['publish-plugin', '--all-changed', '--base-sha=HEAD~']);
|
||||||
|
expect(
|
||||||
|
printedMessages,
|
||||||
|
containsAllInOrder(<String>[
|
||||||
|
'Checking local repo...',
|
||||||
|
'Local repo is ready!',
|
||||||
|
'Getting existing tags...',
|
||||||
|
'Running `pub publish ` in ${pluginDir1.path}...\n',
|
||||||
|
'The file at The pubspec file at ${pluginDir2.childFile('pubspec.yaml').path} does not exist. Publishing will not happen for plugin2.\nSafe to ignore if the package is deleted in this commit.\n',
|
||||||
|
'Packages released: plugin1',
|
||||||
|
'Done!'
|
||||||
|
]));
|
||||||
|
|
||||||
|
expect(processRunner.pushTagsArgs, isNotEmpty);
|
||||||
|
expect(processRunner.pushTagsArgs.length, 3);
|
||||||
|
expect(processRunner.pushTagsArgs[0], 'push');
|
||||||
|
expect(processRunner.pushTagsArgs[1], 'upstream');
|
||||||
|
expect(processRunner.pushTagsArgs[2], 'plugin1-v0.0.2');
|
||||||
|
});
|
||||||
|
|
||||||
|
test(
|
||||||
|
'versions revert do not trigger releases. Also prints out warning message.',
|
||||||
|
() async {
|
||||||
|
// Non-federated
|
||||||
|
final Directory pluginDir1 = createFakePlugin('plugin1',
|
||||||
|
withSingleExample: true, packagesDirectory: mockPackagesDir);
|
||||||
|
// federated
|
||||||
|
final Directory pluginDir2 = createFakePlugin('plugin2',
|
||||||
|
withSingleExample: true,
|
||||||
|
parentDirectoryName: 'plugin2',
|
||||||
|
packagesDirectory: mockPackagesDir);
|
||||||
|
createFakePubspec(pluginDir1,
|
||||||
|
name: 'plugin1',
|
||||||
|
includeVersion: true,
|
||||||
|
isFlutter: false,
|
||||||
|
version: '0.0.2');
|
||||||
|
createFakePubspec(pluginDir2,
|
||||||
|
name: 'plugin2',
|
||||||
|
includeVersion: true,
|
||||||
|
isFlutter: false,
|
||||||
|
version: '0.0.2');
|
||||||
|
await gitDir.runCommand(<String>['add', '-A']);
|
||||||
|
await gitDir.runCommand(<String>['commit', '-m', 'Add plugins']);
|
||||||
|
// Immediately return 0 when running `pub publish`.
|
||||||
|
processRunner.mockPublishCompleteCode = 0;
|
||||||
|
mockStdin.readLineOutput = 'y';
|
||||||
|
await commandRunner
|
||||||
|
.run(<String>['publish-plugin', '--all-changed', '--base-sha=HEAD~']);
|
||||||
|
expect(
|
||||||
|
printedMessages,
|
||||||
|
containsAllInOrder(<String>[
|
||||||
|
'Checking local repo...',
|
||||||
|
'Local repo is ready!',
|
||||||
|
'Getting existing tags...',
|
||||||
|
'Running `pub publish ` in ${pluginDir1.path}...\n',
|
||||||
|
'Running `pub publish ` in ${pluginDir2.path}...\n',
|
||||||
|
'Packages released: plugin1, plugin2',
|
||||||
|
'Done!'
|
||||||
|
]));
|
||||||
|
expect(processRunner.pushTagsArgs, isNotEmpty);
|
||||||
|
expect(processRunner.pushTagsArgs[0], 'push');
|
||||||
|
expect(processRunner.pushTagsArgs[1], 'upstream');
|
||||||
|
expect(processRunner.pushTagsArgs[2], 'plugin1-v0.0.2');
|
||||||
|
expect(processRunner.pushTagsArgs[3], 'push');
|
||||||
|
expect(processRunner.pushTagsArgs[4], 'upstream');
|
||||||
|
expect(processRunner.pushTagsArgs[5], 'plugin2-v0.0.2');
|
||||||
|
|
||||||
|
processRunner.pushTagsArgs.clear();
|
||||||
|
printedMessages.clear();
|
||||||
|
|
||||||
|
final List<String> plugin1Pubspec =
|
||||||
|
pluginDir1.childFile('pubspec.yaml').readAsLinesSync();
|
||||||
|
plugin1Pubspec[plugin1Pubspec.indexWhere(
|
||||||
|
(String element) => element.contains('version:'))] = 'version: 0.0.1';
|
||||||
|
pluginDir1
|
||||||
|
.childFile('pubspec.yaml')
|
||||||
|
.writeAsStringSync(plugin1Pubspec.join('\n'));
|
||||||
|
final List<String> plugin2Pubspec =
|
||||||
|
pluginDir2.childFile('pubspec.yaml').readAsLinesSync();
|
||||||
|
plugin2Pubspec[plugin2Pubspec.indexWhere(
|
||||||
|
(String element) => element.contains('version:'))] = 'version: 0.0.1';
|
||||||
|
pluginDir2
|
||||||
|
.childFile('pubspec.yaml')
|
||||||
|
.writeAsStringSync(plugin2Pubspec.join('\n'));
|
||||||
|
await gitDir.runCommand(<String>['add', '-A']);
|
||||||
|
await gitDir
|
||||||
|
.runCommand(<String>['commit', '-m', 'Update versions to 0.0.1']);
|
||||||
|
|
||||||
|
await commandRunner
|
||||||
|
.run(<String>['publish-plugin', '--all-changed', '--base-sha=HEAD~']);
|
||||||
|
expect(
|
||||||
|
printedMessages,
|
||||||
|
containsAllInOrder(<String>[
|
||||||
|
'Checking local repo...',
|
||||||
|
'Local repo is ready!',
|
||||||
|
'Getting existing tags...',
|
||||||
|
'The new version (0.0.1) is lower than the current version (0.0.2) for plugin1.\nThis git commit is a revert, no release is tagged.',
|
||||||
|
'The new version (0.0.1) is lower than the current version (0.0.2) for plugin2.\nThis git commit is a revert, no release is tagged.',
|
||||||
|
'Done!'
|
||||||
|
]));
|
||||||
|
|
||||||
|
expect(processRunner.pushTagsArgs, isEmpty);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('No version change does not release any plugins', () async {
|
||||||
|
// Non-federated
|
||||||
|
final Directory pluginDir1 = createFakePlugin('plugin1',
|
||||||
|
withSingleExample: true, packagesDirectory: mockPackagesDir);
|
||||||
|
// federated
|
||||||
|
final Directory pluginDir2 = createFakePlugin('plugin2',
|
||||||
|
withSingleExample: true,
|
||||||
|
parentDirectoryName: 'plugin2',
|
||||||
|
packagesDirectory: mockPackagesDir);
|
||||||
|
createFakePubspec(pluginDir1,
|
||||||
|
name: 'plugin1',
|
||||||
|
includeVersion: true,
|
||||||
|
isFlutter: false,
|
||||||
|
version: '0.0.1');
|
||||||
|
createFakePubspec(pluginDir2,
|
||||||
|
name: 'plugin2',
|
||||||
|
includeVersion: true,
|
||||||
|
isFlutter: false,
|
||||||
|
version: '0.0.1');
|
||||||
|
|
||||||
|
io.Process.runSync('git', <String>['init'],
|
||||||
|
workingDirectory: mockPackagesDir.path);
|
||||||
|
gitDir = await GitDir.fromExisting(mockPackagesDir.path);
|
||||||
|
await gitDir.runCommand(<String>['add', '-A']);
|
||||||
|
await gitDir.runCommand(<String>['commit', '-m', 'Add plugins']);
|
||||||
|
|
||||||
|
pluginDir1.childFile('plugin1.dart').createSync();
|
||||||
|
pluginDir2.childFile('plugin2.dart').createSync();
|
||||||
|
await gitDir.runCommand(<String>['add', '-A']);
|
||||||
|
await gitDir.runCommand(<String>['commit', '-m', 'Add dart files']);
|
||||||
|
|
||||||
|
// Immediately return 0 when running `pub publish`.
|
||||||
|
processRunner.mockPublishCompleteCode = 0;
|
||||||
|
mockStdin.readLineOutput = 'y';
|
||||||
|
await commandRunner
|
||||||
|
.run(<String>['publish-plugin', '--all-changed', '--base-sha=HEAD~']);
|
||||||
|
expect(
|
||||||
|
printedMessages,
|
||||||
|
containsAllInOrder(<String>[
|
||||||
|
'Checking local repo...',
|
||||||
|
'Local repo is ready!',
|
||||||
|
'No version updates in this commit.',
|
||||||
|
'Done!'
|
||||||
|
]));
|
||||||
|
expect(processRunner.pushTagsArgs, isEmpty);
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
class TestProcessRunner extends ProcessRunner {
|
class TestProcessRunner extends ProcessRunner {
|
||||||
final List<io.ProcessResult> results = <io.ProcessResult>[];
|
final List<io.ProcessResult> results = <io.ProcessResult>[];
|
||||||
final MockProcess mockPublishProcess = MockProcess();
|
// Most recent returned publish process.
|
||||||
|
MockProcess mockPublishProcess;
|
||||||
final List<String> mockPublishArgs = <String>[];
|
final List<String> mockPublishArgs = <String>[];
|
||||||
final MockProcessResult mockPushTagsResult = MockProcessResult();
|
final MockProcessResult mockPushTagsResult = MockProcessResult();
|
||||||
final List<String> pushTagsArgs = <String>[];
|
final List<String> pushTagsArgs = <String>[];
|
||||||
|
|
||||||
|
String mockPublishStdout;
|
||||||
|
String mockPublishStderr;
|
||||||
|
int mockPublishCompleteCode;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<io.ProcessResult> run(
|
Future<io.ProcessResult> run(
|
||||||
String executable,
|
String executable,
|
||||||
@ -362,23 +888,42 @@ class TestProcessRunner extends ProcessRunner {
|
|||||||
args[0] == 'pub' &&
|
args[0] == 'pub' &&
|
||||||
args[1] == 'publish');
|
args[1] == 'publish');
|
||||||
mockPublishArgs.addAll(args);
|
mockPublishArgs.addAll(args);
|
||||||
|
mockPublishProcess = MockProcess();
|
||||||
|
if (mockPublishStdout != null) {
|
||||||
|
mockPublishProcess.stdoutController.add(utf8.encode(mockPublishStdout));
|
||||||
|
}
|
||||||
|
if (mockPublishStderr != null) {
|
||||||
|
mockPublishProcess.stderrController.add(utf8.encode(mockPublishStderr));
|
||||||
|
}
|
||||||
|
if (mockPublishCompleteCode != null) {
|
||||||
|
mockPublishProcess.exitCodeCompleter.complete(mockPublishCompleteCode);
|
||||||
|
}
|
||||||
|
|
||||||
return mockPublishProcess;
|
return mockPublishProcess;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MockStdin extends Mock implements io.Stdin {
|
class MockStdin extends Mock implements io.Stdin {
|
||||||
final StreamController<List<int>> controller = StreamController<List<int>>();
|
List<List<int>> mockUserInputs = <List<int>>[];
|
||||||
|
StreamController<List<int>> _controller;
|
||||||
String readLineOutput;
|
String readLineOutput;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Stream<S> transform<S>(StreamTransformer<List<int>, S> streamTransformer) {
|
Stream<S> transform<S>(StreamTransformer<List<int>, S> streamTransformer) {
|
||||||
return controller.stream.transform(streamTransformer);
|
// In the test context, only one `PublishPluginCommand` object is created for a single test case.
|
||||||
|
// However, sometimes, we need to run multiple commands in a single test case.
|
||||||
|
// In such situation, this `MockStdin`'s StreamController might be listened to more than once, which is not allowed.
|
||||||
|
//
|
||||||
|
// Create a new controller every time so this Stdin could be listened to multiple times.
|
||||||
|
_controller = StreamController<List<int>>();
|
||||||
|
mockUserInputs.forEach(_addUserInputsToSteam);
|
||||||
|
return _controller.stream.transform(streamTransformer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
StreamSubscription<List<int>> listen(void onData(List<int> event),
|
StreamSubscription<List<int>> listen(void onData(List<int> event),
|
||||||
{Function onError, void onDone(), bool cancelOnError}) {
|
{Function onError, void onDone(), bool cancelOnError}) {
|
||||||
return controller.stream.listen(onData,
|
return _controller.stream.listen(onData,
|
||||||
onError: onError, onDone: onDone, cancelOnError: cancelOnError);
|
onError: onError, onDone: onDone, cancelOnError: cancelOnError);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -387,6 +932,15 @@ class MockStdin extends Mock implements io.Stdin {
|
|||||||
{Encoding encoding = io.systemEncoding,
|
{Encoding encoding = io.systemEncoding,
|
||||||
bool retainNewlines = false}) =>
|
bool retainNewlines = false}) =>
|
||||||
readLineOutput;
|
readLineOutput;
|
||||||
|
|
||||||
|
void _addUserInputsToSteam(List<int> input) => _controller.add(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
class MockProcessResult extends Mock implements io.ProcessResult {}
|
class MockProcessResult extends Mock implements io.ProcessResult {
|
||||||
|
MockProcessResult({int exitCode = 0}) : _exitCode = exitCode;
|
||||||
|
|
||||||
|
final int _exitCode;
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get exitCode => _exitCode;
|
||||||
|
}
|
||||||
|
@ -49,6 +49,7 @@ Directory createFakePlugin(
|
|||||||
bool isWindowsPlugin = false,
|
bool isWindowsPlugin = false,
|
||||||
bool includeChangeLog = false,
|
bool includeChangeLog = false,
|
||||||
bool includeVersion = false,
|
bool includeVersion = false,
|
||||||
|
String version = '0.0.1',
|
||||||
String parentDirectoryName = '',
|
String parentDirectoryName = '',
|
||||||
Directory packagesDirectory,
|
Directory packagesDirectory,
|
||||||
}) {
|
}) {
|
||||||
@ -73,6 +74,7 @@ Directory createFakePlugin(
|
|||||||
isMacOsPlugin: isMacOsPlugin,
|
isMacOsPlugin: isMacOsPlugin,
|
||||||
isWindowsPlugin: isWindowsPlugin,
|
isWindowsPlugin: isWindowsPlugin,
|
||||||
includeVersion: includeVersion,
|
includeVersion: includeVersion,
|
||||||
|
version: version
|
||||||
);
|
);
|
||||||
if (includeChangeLog) {
|
if (includeChangeLog) {
|
||||||
createFakeCHANGELOG(pluginDirectory, '''
|
createFakeCHANGELOG(pluginDirectory, '''
|
||||||
@ -85,14 +87,14 @@ Directory createFakePlugin(
|
|||||||
final Directory exampleDir = pluginDirectory.childDirectory('example')
|
final Directory exampleDir = pluginDirectory.childDirectory('example')
|
||||||
..createSync();
|
..createSync();
|
||||||
createFakePubspec(exampleDir,
|
createFakePubspec(exampleDir,
|
||||||
name: '${name}_example', isFlutter: isFlutter);
|
name: '${name}_example', isFlutter: isFlutter, includeVersion: false, publishTo: 'none');
|
||||||
} else if (withExamples.isNotEmpty) {
|
} else if (withExamples.isNotEmpty) {
|
||||||
final Directory exampleDir = pluginDirectory.childDirectory('example')
|
final Directory exampleDir = pluginDirectory.childDirectory('example')
|
||||||
..createSync();
|
..createSync();
|
||||||
for (final String example in withExamples) {
|
for (final String example in withExamples) {
|
||||||
final Directory currentExample = exampleDir.childDirectory(example)
|
final Directory currentExample = exampleDir.childDirectory(example)
|
||||||
..createSync();
|
..createSync();
|
||||||
createFakePubspec(currentExample, name: example, isFlutter: isFlutter);
|
createFakePubspec(currentExample, name: example, isFlutter: isFlutter, includeVersion: false, publishTo: 'none');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,6 +125,7 @@ void createFakePubspec(
|
|||||||
bool isLinuxPlugin = false,
|
bool isLinuxPlugin = false,
|
||||||
bool isMacOsPlugin = false,
|
bool isMacOsPlugin = false,
|
||||||
bool isWindowsPlugin = false,
|
bool isWindowsPlugin = false,
|
||||||
|
String publishTo = 'http://no_pub_server.com',
|
||||||
String version = '0.0.1',
|
String version = '0.0.1',
|
||||||
}) {
|
}) {
|
||||||
parent.childFile('pubspec.yaml').createSync();
|
parent.childFile('pubspec.yaml').createSync();
|
||||||
@ -180,7 +183,11 @@ dependencies:
|
|||||||
if (includeVersion) {
|
if (includeVersion) {
|
||||||
yaml += '''
|
yaml += '''
|
||||||
version: $version
|
version: $version
|
||||||
publish_to: http://no_pub_server.com # Hardcoded safeguard to prevent this from somehow being published by a broken test.
|
''';
|
||||||
|
}
|
||||||
|
if (publishTo.isNotEmpty) {
|
||||||
|
yaml += '''
|
||||||
|
publish_to: $publishTo # Hardcoded safeguard to prevent this from somehow being published by a broken test.
|
||||||
''';
|
''';
|
||||||
}
|
}
|
||||||
parent.childFile('pubspec.yaml').writeAsStringSync(yaml);
|
parent.childFile('pubspec.yaml').writeAsStringSync(yaml);
|
||||||
|
Reference in New Issue
Block a user