Skip to content

Commit

Permalink
[tool] add an skip-confirmation flag to publish-package for running…
Browse files Browse the repository at this point in the history
… the command on ci (flutter#3842)

the skip-confirmation flag will add a --force flag to pub publish, it will also let users to skip the y/n question when pushing tags to remote.

Fixes flutter#79830
  • Loading branch information
Chris Yang committed May 11, 2021
1 parent 145b6cf commit e674e0d
Show file tree
Hide file tree
Showing 3 changed files with 171 additions and 57 deletions.
1 change: 1 addition & 0 deletions script/tool/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

- Add `against-pub` flag for version-check, which allows the command to check version with pub.
- Add `machine` flag for publish-check, which replaces outputs to something parsable by machines.
- Add `skip-conformation` flag to publish-plugin to allow auto publishing.

## 0.1.1

Expand Down
115 changes: 90 additions & 25 deletions script/tool/lib/src/publish_plugin_command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,12 @@ class PublishPluginCommand extends PluginCommand {
defaultsTo: false,
negatable: true,
);
argParser.addFlag(_skipConfirmationFlag,
help: 'Run the command without asking for Y/N inputs.\n'
'This command will add a `--force` flag to the `pub publish` command if it is not added with $_pubFlagsOption\n'
'It also skips the y/n inputs when pushing tags to remote.\n',
defaultsTo: false,
negatable: true);
}

static const String _packageOption = 'package';
Expand All @@ -93,6 +99,9 @@ class PublishPluginCommand extends PluginCommand {
static const String _remoteOption = 'remote';
static const String _allChangedFlag = 'all-changed';
static const String _dryRunFlag = 'dry-run';
static const String _skipConfirmationFlag = 'skip-confirmation';

static const String _pubCredentialName = 'PUB_CREDENTIALS';

// Version tags should follow <package-name>-v<semantic-version>. For example,
// `flutter_plugin_tools-v0.0.24`.
Expand All @@ -103,7 +112,9 @@ class PublishPluginCommand extends PluginCommand {

@override
final String description =
'Attempts to publish the given plugin and tag its release on GitHub.';
'Attempts to publish the given plugin and tag its release on GitHub.\n'
'If running this on CI, an environment variable named $_pubCredentialName must be set to a String that represents the pub credential JSON.\n'
'WARNING: Do not check in the content of pub credential JSON, it should only come from secure sources.';

final Print _print;
final io.Stdin _stdin;
Expand Down Expand Up @@ -267,7 +278,8 @@ Safe to ignore if the package is deleted in this commit.
}

if (pubspec.version == null) {
_print('No version found. A package that intentionally has no version should be marked "publish_to: none"');
_print(
'No version found. A package that intentionally has no version should be marked "publish_to: none"');
return _CheckNeedsReleaseResult.failure;
}

Expand Down Expand Up @@ -408,24 +420,33 @@ Safe to ignore if the package is deleted in this commit.
argResults[_pubFlagsOption] as List<String>;
_print(
'Running `pub publish ${publishFlags.join(' ')}` in ${packageDir.absolute.path}...\n');
if (!(argResults[_dryRunFlag] as bool)) {
final io.Process publish = await processRunner.start(
'flutter', <String>['pub', 'publish'] + publishFlags,
workingDirectory: packageDir);
publish.stdout
.transform(utf8.decoder)
.listen((String data) => _print(data));
publish.stderr
.transform(utf8.decoder)
.listen((String data) => _print(data));
_stdinSubscription ??= _stdin
.transform(utf8.decoder)
.listen((String data) => publish.stdin.writeln(data));
final int result = await publish.exitCode;
if (result != 0) {
_print('Publish ${packageDir.basename} failed.');
return false;
}
if (argResults[_dryRunFlag] as bool) {
return true;
}

if (argResults[_skipConfirmationFlag] as bool) {
publishFlags.add('--force');
}
if (publishFlags.contains('--force')) {
_ensureValidPubCredential();
}

final io.Process publish = await processRunner.start(
'flutter', <String>['pub', 'publish'] + publishFlags,
workingDirectory: packageDir);
publish.stdout
.transform(utf8.decoder)
.listen((String data) => _print(data));
publish.stderr
.transform(utf8.decoder)
.listen((String data) => _print(data));
_stdinSubscription ??= _stdin
.transform(utf8.decoder)
.listen((String data) => publish.stdin.writeln(data));
final int result = await publish.exitCode;
if (result != 0) {
_print('Publish ${packageDir.basename} failed.');
return false;
}
return true;
}
Expand Down Expand Up @@ -453,11 +474,13 @@ Safe to ignore if the package is deleted in this commit.
@required String remoteUrl,
}) async {
assert(remote != null && tag != null && remoteUrl != null);
_print('Ready to push $tag to $remoteUrl (y/n)?');
final String input = _stdin.readLineSync();
if (input.toLowerCase() != 'y') {
_print('Tag push canceled.');
return false;
if (!(argResults[_skipConfirmationFlag] as bool)) {
_print('Ready to push $tag to $remoteUrl (y/n)?');
final String input = _stdin.readLineSync();
if (input.toLowerCase() != 'y') {
_print('Tag push canceled.');
return false;
}
}
if (!(argResults[_dryRunFlag] as bool)) {
final io.ProcessResult result = await processRunner.run(
Expand All @@ -473,8 +496,50 @@ Safe to ignore if the package is deleted in this commit.
}
return true;
}

void _ensureValidPubCredential() {
final File credentialFile = fileSystem.file(_credentialsPath);
if (credentialFile.existsSync() &&
credentialFile.readAsStringSync().isNotEmpty) {
return;
}
final String credential = io.Platform.environment[_pubCredentialName];
if (credential == null) {
printErrorAndExit(errorMessage: '''
No pub credential available. Please check if `~/.pub-cache/credentials.json` is valid.
If running this command on CI, you can set the pub credential content in the $_pubCredentialName environment variable.
''');
}
credentialFile.openSync(mode: FileMode.writeOnlyAppend)
..writeStringSync(credential)
..closeSync();
}

/// Returns the correct path where the pub credential is stored.
@visibleForTesting
static String getCredentialPath() {
return _credentialsPath;
}
}

/// The path in which pub expects to find its credentials file.
final String _credentialsPath = () {
// This follows the same logic as pub:
// https://github.com/dart-lang/pub/blob/d99b0d58f4059d7bb4ac4616fd3d54ec00a2b5d4/lib/src/system_cache.dart#L34-L43
String cacheDir;
final String pubCache = io.Platform.environment['PUB_CACHE'];
print(pubCache);
if (pubCache != null) {
cacheDir = pubCache;
} else if (io.Platform.isWindows) {
final String appData = io.Platform.environment['APPDATA'];
cacheDir = p.join(appData, 'Pub', 'Cache');
} else {
cacheDir = p.join(io.Platform.environment['HOME'], '.pub-cache');
}
return p.join(cacheDir, 'credentials.json');
}();

enum _CheckNeedsReleaseResult {
// The package needs to be released.
release,
Expand Down

0 comments on commit e674e0d

Please sign in to comment.