File Coverage

blib/lib/Dist/Zilla/Plugin/GitHub.pm
Criterion Covered Total %
statement 40 67 59.7
branch 4 20 20.0
condition 2 11 18.1
subroutine 13 14 92.8
pod n/a
total 59 112 52.6


line stmt bran cond sub pod time code
1             package Dist::Zilla::Plugin::GitHub; # git description: v0.47-12-g6b55af0
2             # ABSTRACT: Plugins to integrate Dist::Zilla with GitHub
3 1     1   138355 use strict;
  1         9  
  1         25  
4 1     1   4 use warnings;
  1         2  
  1         31  
5              
6             our $VERSION = '0.48';
7              
8 1     1   5 use JSON::MaybeXS;
  1         1  
  1         41  
9 1     1   499 use Moose;
  1         396842  
  1         6  
10 1     1   6286 use Try::Tiny;
  1         3  
  1         57  
11 1     1   892 use HTTP::Tiny;
  1         38212  
  1         39  
12 1     1   486 use Git::Wrapper;
  1         22378  
  1         40  
13 1     1   7 use Class::Load qw(try_load_class);
  1         2  
  1         998  
14              
15             has remote => (
16             is => 'ro',
17             isa => 'Maybe[Str]',
18             default => 'origin'
19             );
20              
21             has repo => (
22             is => 'ro',
23             isa => 'Maybe[Str]'
24             );
25              
26             has api => (
27             is => 'ro',
28             isa => 'Str',
29             default => 'https://api.github.com'
30             );
31              
32             has prompt_2fa => (
33             is => 'rw',
34             isa => 'Bool',
35             default => 0
36             );
37              
38             has _login => (
39             is => 'ro',
40             isa => 'Maybe[Str]',
41             lazy => 1,
42             builder => '_build_login',
43             );
44              
45             has _credentials => (
46             is => 'ro',
47             isa => 'HashRef',
48             lazy => 1,
49             builder => '_build_credentials',
50             );
51              
52             #pod =head1 DESCRIPTION
53             #pod
54             #pod B<Dist-Zilla-Plugin-GitHub> is a set of plugins for L<Dist::Zilla> intended
55             #pod to more easily integrate L<GitHub|https://github.com> in the C<dzil> workflow.
56             #pod
57             #pod The following is the list of the plugins shipped in this distribution:
58             #pod
59             #pod =over 4
60             #pod
61             #pod =item * L<Dist::Zilla::Plugin::GitHub::Create> Create GitHub repo on C<dzil new>
62             #pod
63             #pod =item * L<Dist::Zilla::Plugin::GitHub::Update> Update GitHub repo info on release
64             #pod
65             #pod =item * L<Dist::Zilla::Plugin::GitHub::Meta> Add GitHub repo info to F<META.{yml,json}>
66             #pod
67             #pod =back
68             #pod
69             #pod This distribution also provides a plugin bundle, L<Dist::Zilla::PluginBundle::GitHub>,
70             #pod which provides L<GitHub::Meta|Dist::Zilla::Plugin::GitHub::Meta> and
71             #pod L<[GitHub::Update|Dist::Zilla::Plugin::GitHub::Update> together in one convenient bundle.
72             #pod
73             #pod This distribution also provides an additional C<dzil> command (L<dzil
74             #pod gh|Dist::Zilla::App::Command::gh>) and a L<plugin
75             #pod bundle|Dist::Zilla::PluginBundle::GitHub>.
76             #pod
77             #pod =cut
78              
79             sub _build_login {
80 0     0   0 my $self = shift;
81              
82 0         0 my ($login);
83              
84 0 0       0 my %identity = Config::Identity::GitHub->load
85             if try_load_class('Config::Identity::GitHub');
86              
87 0 0       0 if (%identity) {
88 0         0 $login = $identity{login};
89             } else {
90 0         0 $login = `git config github.user`; chomp $login;
  0         0  
91             }
92              
93 0 0       0 if (!$login) {
94 0 0       0 my $error = %identity ?
95             "Err: missing value 'user' in ~/.github" :
96             "Err: Missing value 'github.user' in git config";
97              
98 0         0 $self->log($error);
99 0         0 return undef;
100             }
101              
102 0         0 return $login;
103             }
104              
105             sub _build_credentials {
106             my $self = shift;
107              
108             my ($login, $pass, $token);
109              
110             $login = $self->_login;
111              
112             if (!$login) {
113             return {};
114             }
115              
116             my %identity = Config::Identity::GitHub->load
117             if try_load_class('Config::Identity::GitHub');
118              
119             if (%identity) {
120             $token = $identity{token};
121             $pass = $identity{password};
122             } else {
123             $token = `git config github.token`; chomp $token;
124             $pass = `git config github.password`; chomp $pass;
125             }
126              
127             if (!$pass and !$token) {
128             $pass = $self->zilla->chrome->prompt_str(
129             "GitHub password for '$login'", { noecho => 1 },
130             );
131             }
132              
133             return { login => $login, pass => $pass, token => $token };
134             }
135              
136             sub _has_credentials {
137 1     1   7 my $self = shift;
138 1         2 return keys %{$self->_credentials};
  1         52  
139             }
140              
141             sub _auth_headers {
142 1     1   78 my $self = shift;
143              
144 1         31 my $credentials = $self->_credentials;
145              
146 1         28 my %headers = ( Accept => 'application/vnd.github.v3+json' );
147 1 50       7 if ($credentials->{pass}) {
    50          
148 0         0 require MIME::Base64;
149 0         0 my $basic = MIME::Base64::encode_base64("$credentials->{login}:$credentials->{pass}", '');
150 0         0 $headers{Authorization} = "Basic $basic";
151             }
152             elsif ($credentials->{token}) {
153 0         0 $headers{Authorization} = "token $credentials->{token}";
154             }
155              
156             # This can't be done at object creation because we autodetect the
157             # need for 2FA when GitHub says we need it, so we won't know to
158             # prompt at object creation time.
159 1 50       44 if ($self->prompt_2fa) {
160 0         0 my $otp = $self->zilla->chrome->prompt_str(
161             "GitHub two-factor authentication code for '$credentials->{login}'",
162             { noecho => 1 },
163             );
164              
165 0         0 $headers{'X-GitHub-OTP'} = $otp;
166 0         0 $self->log([ "Using two-factor authentication" ]);
167             }
168              
169 1         28 return \%headers;
170             }
171              
172             sub _get_repo_name {
173             my ($self, $login) = @_;
174              
175             my $repo;
176             my $git = Git::Wrapper->new('./');
177              
178             $repo = $self->repo if $self->repo;
179              
180             my $url;
181             {
182             local $ENV{LANG}='C';
183             ($url) = map /Fetch URL: (.*)/,
184             $git->remote('show', '-n', $self->remote);
185             }
186              
187             $url =~ /github\.com.*?[:\/](.*)\.git$/;
188             $repo = $1 unless $repo and not $1;
189              
190             $repo = $self->zilla->name unless $repo;
191              
192             if ($repo !~ /.*\/.*/) {
193             $login = $self->_login;
194             if (defined $login) {
195             $repo = "$login/$repo";
196             }
197             }
198              
199             return $repo;
200             }
201              
202             sub _check_response {
203 2     2   10 my ($self, $response) = @_;
204              
205             try {
206 2     2   135 my $json_text = decode_json($response->{content});
207              
208 0 0       0 if (!$response->{success}) {
209             return 'redo' if (($response->{status} eq '401') and
210 0 0 0     0 (($response->{headers}{'x-github-otp'} // '') =~ /^required/));
      0        
211              
212 0         0 require Data::Dumper;
213 0         0 $self->log("Err: ", Data::Dumper->new([ $response ])->Indent(2)->Terse(1)->Sortkeys(1)->Dump);
214 0         0 return;
215             }
216              
217 0         0 return $json_text;
218             } catch {
219 2     2   35 $self->log("Error: $_");
220 2 50 33     533 if ($response and !$response->{success} and
      33        
221             $response->{status} eq '599') {
222             #possibly HTTP::Tiny error
223 0         0 $self->log("Err: ", $response->{content});
224 0         0 return;
225             }
226              
227 2         11 $self->log("Error communicating with GitHub: $_");
228              
229 2         577 return;
230 2         32 };
231             }
232              
233             __PACKAGE__->meta->make_immutable;
234             1; # End of Dist::Zilla::Plugin::GitHub
235              
236             __END__
237              
238             =pod
239              
240             =encoding UTF-8
241              
242             =head1 NAME
243              
244             Dist::Zilla::Plugin::GitHub - Plugins to integrate Dist::Zilla with GitHub
245              
246             =head1 VERSION
247              
248             version 0.48
249              
250             =head1 DESCRIPTION
251              
252             B<Dist-Zilla-Plugin-GitHub> is a set of plugins for L<Dist::Zilla> intended
253             to more easily integrate L<GitHub|https://github.com> in the C<dzil> workflow.
254              
255             The following is the list of the plugins shipped in this distribution:
256              
257             =over 4
258              
259             =item * L<Dist::Zilla::Plugin::GitHub::Create> Create GitHub repo on C<dzil new>
260              
261             =item * L<Dist::Zilla::Plugin::GitHub::Update> Update GitHub repo info on release
262              
263             =item * L<Dist::Zilla::Plugin::GitHub::Meta> Add GitHub repo info to F<META.{yml,json}>
264              
265             =back
266              
267             This distribution also provides a plugin bundle, L<Dist::Zilla::PluginBundle::GitHub>,
268             which provides L<GitHub::Meta|Dist::Zilla::Plugin::GitHub::Meta> and
269             L<[GitHub::Update|Dist::Zilla::Plugin::GitHub::Update> together in one convenient bundle.
270              
271             This distribution also provides an additional C<dzil> command (L<dzil
272             gh|Dist::Zilla::App::Command::gh>) and a L<plugin
273             bundle|Dist::Zilla::PluginBundle::GitHub>.
274              
275             =head1 SUPPORT
276              
277             Bugs may be submitted through L<the RT bug tracker|https://rt.cpan.org/Public/Dist/Display.html?Name=Dist-Zilla-Plugin-GitHub>
278             (or L<bug-Dist-Zilla-Plugin-GitHub@rt.cpan.org|mailto:bug-Dist-Zilla-Plugin-GitHub@rt.cpan.org>).
279              
280             There is also a mailing list available for users of this distribution, at
281             L<http://dzil.org/#mailing-list>.
282              
283             There is also an irc channel available for users of this distribution, at
284             L<C<#distzilla> on C<irc.perl.org>|irc://irc.perl.org/#distzilla>.
285              
286             =head1 AUTHOR
287              
288             Alessandro Ghedini <alexbio@cpan.org>
289              
290             =head1 CONTRIBUTORS
291              
292             =for stopwords Alessandro Ghedini Karen Etheridge Dave Rolsky Mike Friedman Jeffrey Ryan Thalhammer Joelle Maslak Doherty Rafael Kitover Alexandr Ciornii Brian Phillips Chris Weyl Ioan Rogers Jose Luis Perez Diez Mohammad S Anwar Paul Cochrane Ricardo Signes Vyacheslav Matyukhin
293              
294             =over 4
295              
296             =item *
297              
298             Alessandro Ghedini <alessandro@ghedini.me>
299              
300             =item *
301              
302             Karen Etheridge <ether@cpan.org>
303              
304             =item *
305              
306             Dave Rolsky <autarch@urth.org>
307              
308             =item *
309              
310             Mike Friedman <mike.friedman@10gen.com>
311              
312             =item *
313              
314             Jeffrey Ryan Thalhammer <jeff@imaginative-software.com>
315              
316             =item *
317              
318             Joelle Maslak <jmaslak@antelope.net>
319              
320             =item *
321              
322             Mike Doherty <doherty@cs.dal.ca>
323              
324             =item *
325              
326             Rafael Kitover <rkitover@cpan.org>
327              
328             =item *
329              
330             Alexandr Ciornii <alexchorny@gmail.com>
331              
332             =item *
333              
334             Brian Phillips <bphillips@cpan.org>
335              
336             =item *
337              
338             Chris Weyl <cweyl@alumni.drew.edu>
339              
340             =item *
341              
342             Ioan Rogers <ioan.rogers@gmail.com>
343              
344             =item *
345              
346             Jose Luis Perez Diez <jluis@escomposlinux.org>
347              
348             =item *
349              
350             Mohammad S Anwar <mohammad.anwar@yahoo.com>
351              
352             =item *
353              
354             Paul Cochrane <paul.cochrane@posteo.de>
355              
356             =item *
357              
358             Ricardo Signes <rjbs@cpan.org>
359              
360             =item *
361              
362             Vyacheslav Matyukhin <mmcleric@yandex-team.ru>
363              
364             =back
365              
366             =head1 COPYRIGHT AND LICENSE
367              
368             This software is copyright (c) 2011 by Alessandro Ghedini.
369              
370             This is free software; you can redistribute it and/or modify it under
371             the same terms as the Perl 5 programming language system itself.
372              
373             =cut