@@ -84,6 +84,12 @@ class PublishPluginCommand extends PluginCommand {
84
84
defaultsTo: false ,
85
85
negatable: true ,
86
86
);
87
+ argParser.addFlag (_skipConfirmationFlag,
88
+ help: 'Run the command without asking for Y/N inputs.\n '
89
+ 'This command will add a `--force` flag to the `pub publish` command if it is not added with $_pubFlagsOption \n '
90
+ 'It also skips the y/n inputs when pushing tags to remote.\n ' ,
91
+ defaultsTo: false ,
92
+ negatable: true );
87
93
}
88
94
89
95
static const String _packageOption = 'package' ;
@@ -93,6 +99,9 @@ class PublishPluginCommand extends PluginCommand {
93
99
static const String _remoteOption = 'remote' ;
94
100
static const String _allChangedFlag = 'all-changed' ;
95
101
static const String _dryRunFlag = 'dry-run' ;
102
+ static const String _skipConfirmationFlag = 'skip-confirmation' ;
103
+
104
+ static const String _pubCredentialName = 'PUB_CREDENTIALS' ;
96
105
97
106
// Version tags should follow <package-name>-v<semantic-version>. For example,
98
107
// `flutter_plugin_tools-v0.0.24`.
@@ -103,7 +112,9 @@ class PublishPluginCommand extends PluginCommand {
103
112
104
113
@override
105
114
final String description =
106
- 'Attempts to publish the given plugin and tag its release on GitHub.' ;
115
+ 'Attempts to publish the given plugin and tag its release on GitHub.\n '
116
+ 'If running this on CI, an environment variable named $_pubCredentialName must be set to a String that represents the pub credential JSON.\n '
117
+ 'WARNING: Do not check in the content of pub credential JSON, it should only come from secure sources.' ;
107
118
108
119
final Print _print;
109
120
final io.Stdin _stdin;
@@ -267,7 +278,8 @@ Safe to ignore if the package is deleted in this commit.
267
278
}
268
279
269
280
if (pubspec.version == null ) {
270
- _print ('No version found. A package that intentionally has no version should be marked "publish_to: none"' );
281
+ _print (
282
+ 'No version found. A package that intentionally has no version should be marked "publish_to: none"' );
271
283
return _CheckNeedsReleaseResult .failure;
272
284
}
273
285
@@ -408,24 +420,33 @@ Safe to ignore if the package is deleted in this commit.
408
420
argResults[_pubFlagsOption] as List <String >;
409
421
_print (
410
422
'Running `pub publish ${publishFlags .join (' ' )}` in ${packageDir .absolute .path }...\n ' );
411
- if (! (argResults[_dryRunFlag] as bool )) {
412
- final io.Process publish = await processRunner.start (
413
- 'flutter' , < String > ['pub' , 'publish' ] + publishFlags,
414
- workingDirectory: packageDir);
415
- publish.stdout
416
- .transform (utf8.decoder)
417
- .listen ((String data) => _print (data));
418
- publish.stderr
419
- .transform (utf8.decoder)
420
- .listen ((String data) => _print (data));
421
- _stdinSubscription ?? = _stdin
422
- .transform (utf8.decoder)
423
- .listen ((String data) => publish.stdin.writeln (data));
424
- final int result = await publish.exitCode;
425
- if (result != 0 ) {
426
- _print ('Publish ${packageDir .basename } failed.' );
427
- return false ;
428
- }
423
+ if (argResults[_dryRunFlag] as bool ) {
424
+ return true ;
425
+ }
426
+
427
+ if (argResults[_skipConfirmationFlag] as bool ) {
428
+ publishFlags.add ('--force' );
429
+ }
430
+ if (publishFlags.contains ('--force' )) {
431
+ _ensureValidPubCredential ();
432
+ }
433
+
434
+ final io.Process publish = await processRunner.start (
435
+ 'flutter' , < String > ['pub' , 'publish' ] + publishFlags,
436
+ workingDirectory: packageDir);
437
+ publish.stdout
438
+ .transform (utf8.decoder)
439
+ .listen ((String data) => _print (data));
440
+ publish.stderr
441
+ .transform (utf8.decoder)
442
+ .listen ((String data) => _print (data));
443
+ _stdinSubscription ?? = _stdin
444
+ .transform (utf8.decoder)
445
+ .listen ((String data) => publish.stdin.writeln (data));
446
+ final int result = await publish.exitCode;
447
+ if (result != 0 ) {
448
+ _print ('Publish ${packageDir .basename } failed.' );
449
+ return false ;
429
450
}
430
451
return true ;
431
452
}
@@ -453,11 +474,13 @@ Safe to ignore if the package is deleted in this commit.
453
474
@required String remoteUrl,
454
475
}) async {
455
476
assert (remote != null && tag != null && remoteUrl != null );
456
- _print ('Ready to push $tag to $remoteUrl (y/n)?' );
457
- final String input = _stdin.readLineSync ();
458
- if (input.toLowerCase () != 'y' ) {
459
- _print ('Tag push canceled.' );
460
- return false ;
477
+ if (! (argResults[_skipConfirmationFlag] as bool )) {
478
+ _print ('Ready to push $tag to $remoteUrl (y/n)?' );
479
+ final String input = _stdin.readLineSync ();
480
+ if (input.toLowerCase () != 'y' ) {
481
+ _print ('Tag push canceled.' );
482
+ return false ;
483
+ }
461
484
}
462
485
if (! (argResults[_dryRunFlag] as bool )) {
463
486
final io.ProcessResult result = await processRunner.run (
@@ -473,8 +496,50 @@ Safe to ignore if the package is deleted in this commit.
473
496
}
474
497
return true ;
475
498
}
499
+
500
+ void _ensureValidPubCredential () {
501
+ final File credentialFile = fileSystem.file (_credentialsPath);
502
+ if (credentialFile.existsSync () &&
503
+ credentialFile.readAsStringSync ().isNotEmpty) {
504
+ return ;
505
+ }
506
+ final String credential = io.Platform .environment[_pubCredentialName];
507
+ if (credential == null ) {
508
+ printErrorAndExit (errorMessage: '''
509
+ No pub credential available. Please check if `~/.pub-cache/credentials.json` is valid.
510
+ If running this command on CI, you can set the pub credential content in the $_pubCredentialName environment variable.
511
+ ''' );
512
+ }
513
+ credentialFile.openSync (mode: FileMode .writeOnlyAppend)
514
+ ..writeStringSync (credential)
515
+ ..closeSync ();
516
+ }
517
+
518
+ /// Returns the correct path where the pub credential is stored.
519
+ @visibleForTesting
520
+ static String getCredentialPath () {
521
+ return _credentialsPath;
522
+ }
476
523
}
477
524
525
+ /// The path in which pub expects to find its credentials file.
526
+ final String _credentialsPath = () {
527
+ // This follows the same logic as pub:
528
+ // https://github.com/dart-lang/pub/blob/d99b0d58f4059d7bb4ac4616fd3d54ec00a2b5d4/lib/src/system_cache.dart#L34-L43
529
+ String cacheDir;
530
+ final String pubCache = io.Platform .environment['PUB_CACHE' ];
531
+ print (pubCache);
532
+ if (pubCache != null ) {
533
+ cacheDir = pubCache;
534
+ } else if (io.Platform .isWindows) {
535
+ final String appData = io.Platform .environment['APPDATA' ];
536
+ cacheDir = p.join (appData, 'Pub' , 'Cache' );
537
+ } else {
538
+ cacheDir = p.join (io.Platform .environment['HOME' ], '.pub-cache' );
539
+ }
540
+ return p.join (cacheDir, 'credentials.json' );
541
+ }();
542
+
478
543
enum _CheckNeedsReleaseResult {
479
544
// The package needs to be released.
480
545
release,
0 commit comments