File Coverage

blib/lib/Dist/Zilla/Plugin/UploadToCPAN.pm
Criterion Covered Total %
statement 40 42 95.2
branch 6 6 100.0
condition n/a
subroutine 14 16 87.5
pod 0 4 0.0
total 60 68 88.2


line stmt bran cond sub pod time code
1             package Dist::Zilla::Plugin::UploadToCPAN 6.030;
2             # ABSTRACT: upload the dist to CPAN
3              
4 9     9   6968 use Moose;
  9         27  
  9         99  
5             with 'Dist::Zilla::Role::BeforeRelease',
6             'Dist::Zilla::Role::Releaser';
7              
8 9     9   62825 use Dist::Zilla::Pragmas;
  9         26  
  9         79  
9              
10 9     9   115 use File::Spec;
  9         27  
  9         340  
11 9     9   81 use Moose::Util::TypeConstraints;
  9         36  
  9         102  
12 9     9   20964 use Scalar::Util qw(weaken);
  9         28  
  9         696  
13 9     9   65 use Dist::Zilla::Util;
  9         23  
  9         282  
14 9     9   62 use Try::Tiny;
  9         22  
  9         604  
15              
16 9     9   69 use namespace::autoclean;
  9         43  
  9         80  
17              
18             #pod =head1 SYNOPSIS
19             #pod
20             #pod If loaded, this plugin will allow the F<release> command to upload to the CPAN.
21             #pod
22             #pod =head1 DESCRIPTION
23             #pod
24             #pod This plugin looks for configuration in your C<dist.ini> or (more
25             #pod likely) C<~/.dzil/config.ini>:
26             #pod
27             #pod [%PAUSE]
28             #pod username = YOUR-PAUSE-ID
29             #pod password = YOUR-PAUSE-PASSWORD
30             #pod
31             #pod If this configuration does not exist, it can read the configuration from
32             #pod C<~/.pause>, in the same format that L<cpan-upload> requires:
33             #pod
34             #pod user YOUR-PAUSE-ID
35             #pod password YOUR-PAUSE-PASSWORD
36             #pod
37             #pod If neither configuration exists, it will prompt you to enter your
38             #pod username and password during the BeforeRelease phase. Entering a
39             #pod blank username or password will abort the release.
40             #pod
41             #pod You can't put your password in your F<dist.ini>. C'mon now!
42             #pod
43             #pod =cut
44              
45             {
46             package
47             Dist::Zilla::Plugin::UploadToCPAN::_Uploader;
48             # CPAN::Uploader will be loaded later if used
49             our @ISA = 'CPAN::Uploader';
50             # Report CPAN::Uploader's version, not ours:
51 0     0   0 sub _ua_string { CPAN::Uploader->_ua_string }
52              
53             sub log {
54 6     6   2151 my $self = shift;
55 6         59 $self->{'Dist::Zilla'}{plugin}->log(@_);
56             }
57             }
58              
59             #pod =attr credentials_stash
60             #pod
61             #pod This attribute holds the name of a L<PAUSE stash|Dist::Zilla::Stash::PAUSE>
62             #pod that will contain the credentials to be used for the upload. By default,
63             #pod UploadToCPAN will look for a C<%PAUSE> stash.
64             #pod
65             #pod =cut
66              
67             has credentials_stash => (
68             is => 'ro',
69             isa => 'Str',
70             default => '%PAUSE'
71             );
72              
73             has _credentials_stash_obj => (
74             is => 'ro',
75             isa => maybe_type( class_type('Dist::Zilla::Stash::PAUSE') ),
76             lazy => 1,
77             init_arg => undef,
78             default => sub { $_[0]->zilla->stash_named( $_[0]->credentials_stash ) },
79             );
80              
81             sub _credential {
82 8     8   65 my ($self, $name) = @_;
83              
84 8 100       377 return unless my $stash = $self->_credentials_stash_obj;
85 2         100 return $stash->$name;
86             }
87              
88             sub mvp_aliases {
89 13     13 0 2096 return { user => 'username' };
90             }
91              
92             #pod =attr username
93             #pod
94             #pod This option supplies the user's PAUSE username.
95             #pod It will be looked for in the user's PAUSE configuration; if not
96             #pod found, the user will be prompted.
97             #pod
98             #pod =cut
99              
100             has username => (
101             is => 'ro',
102             isa => 'Str',
103             lazy => 1,
104             default => sub {
105             my ($self) = @_;
106             return $self->_credential('username')
107             || $self->pause_cfg->{user}
108             || $self->zilla->chrome->prompt_str("PAUSE username: ");
109             },
110             );
111              
112 0     0 0 0 sub cpanid { shift->username }
113              
114             #pod =attr password
115             #pod
116             #pod This option supplies the user's PAUSE password. It cannot be provided via
117             #pod F<dist.ini>. It will be looked for in the user's PAUSE configuration; if not
118             #pod found, the user will be prompted.
119             #pod
120             #pod =cut
121              
122             has password => (
123             is => 'ro',
124             isa => 'Str',
125             init_arg => undef,
126             lazy => 1,
127             default => sub {
128             my ($self) = @_;
129             my $pw = $self->_credential('password') || $self->pause_cfg->{password};
130              
131             unless ($pw){
132             my $uname = $self->username;
133             $pw = $self->zilla->chrome->prompt_str(
134             "PAUSE password for $uname: ",
135             { noecho => 1 },
136             );
137             }
138              
139             return $pw;
140             },
141             );
142              
143             #pod =attr pause_cfg_file
144             #pod
145             #pod This is the name of the file containing your pause credentials. It defaults
146             #pod F<.pause>. If you give a relative path, it is taken to be relative to
147             #pod L</pause_cfg_dir>.
148             #pod
149             #pod =cut
150              
151             has pause_cfg_file => (
152             is => 'ro',
153             isa => 'Str',
154             lazy => 1,
155             default => sub { '.pause' },
156             );
157              
158             #pod =attr pause_cfg_dir
159             #pod
160             #pod This is the directory for resolving a relative L</pause_cfg_file>.
161             #pod it defaults to the glob expansion of F<~>.
162             #pod
163             #pod =cut
164              
165             has pause_cfg_dir => (
166             is => 'ro',
167             isa => 'Str',
168             lazy => 1,
169             default => sub { Dist::Zilla::Util->homedir },
170             );
171              
172             #pod =attr pause_cfg
173             #pod
174             #pod This is a hashref of defaults loaded from F<~/.pause> -- this attribute is
175             #pod subject to removal in future versions, as the config-loading behavior in
176             #pod CPAN::Uploader is improved.
177             #pod
178             #pod =cut
179              
180             has pause_cfg => (
181             is => 'ro',
182             isa => 'HashRef[Str]',
183             lazy => 1,
184             default => sub {
185             my $self = shift;
186             require CPAN::Uploader;
187             my $file = $self->pause_cfg_file;
188             $file = File::Spec->catfile($self->pause_cfg_dir, $file)
189             unless File::Spec->file_name_is_absolute($file);
190             return {} unless -e $file && -r _;
191             my $cfg = try {
192             CPAN::Uploader->read_config_file($file)
193             } catch {
194             $self->log("Couldn't load credentials from '$file': $_");
195             {};
196             };
197             return $cfg;
198             },
199             );
200              
201             #pod =attr subdir
202             #pod
203             #pod If given, this specifies a subdirectory under the user's home directory to
204             #pod which to upload. Using this option is not recommended.
205             #pod
206             #pod =cut
207              
208             has subdir => (
209             is => 'ro',
210             isa => 'Str',
211             predicate => 'has_subdir',
212             );
213              
214             #pod =attr upload_uri
215             #pod
216             #pod If given, this specifies an alternate URI for the PAUSE upload form. By
217             #pod default, the default supplied by L<CPAN::Uploader> is used. Using this option
218             #pod is not recommended in most cases.
219             #pod
220             #pod =cut
221              
222             has upload_uri => (
223             is => 'ro',
224             isa => 'Str',
225             predicate => 'has_upload_uri',
226             );
227              
228             #pod =attr retries
229             #pod
230             #pod The number of retries to perform on upload failure (5xx response). The default
231             #pod is set to 3 by this plugin. This option will be passed to L<CPAN::Uploader>.
232             #pod
233             #pod =cut
234              
235             has retries => (
236             is => 'ro',
237             isa => 'Int',
238             default => 3,
239             );
240              
241             #pod =attr retry_delay
242             #pod
243             #pod The number of seconds to wait between retries. The default is set to 5 seconds
244             #pod by this plugin. This option will be passed to L<CPAN::Uploader>.
245             #pod
246             #pod =cut
247              
248             has retry_delay => (
249             is => 'ro',
250             isa => 'Int',
251             default => 5,
252             );
253              
254             has uploader => (
255             is => 'ro',
256             isa => 'CPAN::Uploader',
257             lazy => 1,
258             default => sub {
259             my ($self) = @_;
260              
261             # Load the module lazily
262             require CPAN::Uploader;
263             CPAN::Uploader->VERSION('0.103004'); # require HTTPS
264              
265             my $uploader = Dist::Zilla::Plugin::UploadToCPAN::_Uploader->new({
266             user => $self->username,
267             password => $self->password,
268             ($self->has_subdir
269             ? (subdir => $self->subdir) : ()),
270             ($self->has_upload_uri
271             ? (upload_uri => $self->upload_uri) : ()),
272             ($self->retries
273             ? (retries => $self->retries) : ()),
274             ($self->retry_delay
275             ? (retry_delay => $self->retry_delay) : ()),
276             });
277              
278             $uploader->{'Dist::Zilla'}{plugin} = $self;
279             weaken $uploader->{'Dist::Zilla'}{plugin};
280              
281             return $uploader;
282             }
283             );
284              
285             sub before_release {
286 5     5 0 49 my $self = shift;
287              
288 5         36 my $problem;
289             try {
290 5     5   505 for my $attr (qw(username password)) {
291 9         61 $problem = $attr;
292 9 100       441 die unless length $self->$attr;
293             }
294 2         8 undef $problem;
295 5         208 };
296              
297 5 100       1303 $self->log_fatal(['You need to supply a %s', $problem]) if $problem;
298             }
299              
300             sub release {
301 2     2 0 10 my ($self, $archive) = @_;
302              
303 2         105 $self->uploader->upload_file("$archive");
304             }
305              
306             __PACKAGE__->meta->make_immutable;
307             1;
308              
309             __END__
310              
311             =pod
312              
313             =encoding UTF-8
314              
315             =head1 NAME
316              
317             Dist::Zilla::Plugin::UploadToCPAN - upload the dist to CPAN
318              
319             =head1 VERSION
320              
321             version 6.030
322              
323             =head1 SYNOPSIS
324              
325             If loaded, this plugin will allow the F<release> command to upload to the CPAN.
326              
327             =head1 DESCRIPTION
328              
329             This plugin looks for configuration in your C<dist.ini> or (more
330             likely) C<~/.dzil/config.ini>:
331              
332             [%PAUSE]
333             username = YOUR-PAUSE-ID
334             password = YOUR-PAUSE-PASSWORD
335              
336             If this configuration does not exist, it can read the configuration from
337             C<~/.pause>, in the same format that L<cpan-upload> requires:
338              
339             user YOUR-PAUSE-ID
340             password YOUR-PAUSE-PASSWORD
341              
342             If neither configuration exists, it will prompt you to enter your
343             username and password during the BeforeRelease phase. Entering a
344             blank username or password will abort the release.
345              
346             You can't put your password in your F<dist.ini>. C'mon now!
347              
348             =head1 PERL VERSION
349              
350             This module should work on any version of perl still receiving updates from
351             the Perl 5 Porters. This means it should work on any version of perl released
352             in the last two to three years. (That is, if the most recently released
353             version is v5.40, then this module should work on both v5.40 and v5.38.)
354              
355             Although it may work on older versions of perl, no guarantee is made that the
356             minimum required version will not be increased. The version may be increased
357             for any reason, and there is no promise that patches will be accepted to lower
358             the minimum required perl.
359              
360             =head1 ATTRIBUTES
361              
362             =head2 credentials_stash
363              
364             This attribute holds the name of a L<PAUSE stash|Dist::Zilla::Stash::PAUSE>
365             that will contain the credentials to be used for the upload. By default,
366             UploadToCPAN will look for a C<%PAUSE> stash.
367              
368             =head2 username
369              
370             This option supplies the user's PAUSE username.
371             It will be looked for in the user's PAUSE configuration; if not
372             found, the user will be prompted.
373              
374             =head2 password
375              
376             This option supplies the user's PAUSE password. It cannot be provided via
377             F<dist.ini>. It will be looked for in the user's PAUSE configuration; if not
378             found, the user will be prompted.
379              
380             =head2 pause_cfg_file
381              
382             This is the name of the file containing your pause credentials. It defaults
383             F<.pause>. If you give a relative path, it is taken to be relative to
384             L</pause_cfg_dir>.
385              
386             =head2 pause_cfg_dir
387              
388             This is the directory for resolving a relative L</pause_cfg_file>.
389             it defaults to the glob expansion of F<~>.
390              
391             =head2 pause_cfg
392              
393             This is a hashref of defaults loaded from F<~/.pause> -- this attribute is
394             subject to removal in future versions, as the config-loading behavior in
395             CPAN::Uploader is improved.
396              
397             =head2 subdir
398              
399             If given, this specifies a subdirectory under the user's home directory to
400             which to upload. Using this option is not recommended.
401              
402             =head2 upload_uri
403              
404             If given, this specifies an alternate URI for the PAUSE upload form. By
405             default, the default supplied by L<CPAN::Uploader> is used. Using this option
406             is not recommended in most cases.
407              
408             =head2 retries
409              
410             The number of retries to perform on upload failure (5xx response). The default
411             is set to 3 by this plugin. This option will be passed to L<CPAN::Uploader>.
412              
413             =head2 retry_delay
414              
415             The number of seconds to wait between retries. The default is set to 5 seconds
416             by this plugin. This option will be passed to L<CPAN::Uploader>.
417              
418             =head1 AUTHOR
419              
420             Ricardo SIGNES 😏 <cpan@semiotic.systems>
421              
422             =head1 COPYRIGHT AND LICENSE
423              
424             This software is copyright (c) 2023 by Ricardo SIGNES.
425              
426             This is free software; you can redistribute it and/or modify it under
427             the same terms as the Perl 5 programming language system itself.
428              
429             =cut