File Coverage

lib/App/TimeTracker/Command/GitHub.pm
Criterion Covered Total %
statement 20 33 60.6
branch 0 6 0.0
condition n/a
subroutine 7 9 77.7
pod 0 1 0.0
total 27 49 55.1


line stmt bran cond sub pod time code
1             package App::TimeTracker::Command::GitHub;
2 1     1   569 use strict;
  1         1  
  1         26  
3 1     1   4 use warnings;
  1         1  
  1         23  
4 1     1   15 use 5.020;
  1         2  
5              
6             # ABSTRACT: App::TimeTracker GitHub plugin
7 1     1   398 use App::TimeTracker::Utils qw(error_message warning_message);
  1         8451  
  1         64  
8              
9             our $VERSION = "1.000";
10              
11 1     1   383 use Moose::Role;
  1         470995  
  1         5  
12 1     1   5674 use Pithub;
  1         251092  
  1         469  
13              
14             has 'issue' => (
15             is => 'rw',
16             isa => 'Str',
17             documentation => 'github issue',
18             predicate => 'has_issue'
19             );
20              
21             has 'github_client' => (
22             is => 'rw',
23             isa => 'Maybe[Pithub]',
24             lazy_build => 1,
25             traits => ['NoGetopt'],
26             );
27              
28             sub _build_github_client {
29 0     0     my $self = shift;
30 0           my $config = $self->config->{github};
31              
32 0           my %args;
33              
34             # required
35 0           for my $fld (qw(user repo token)) {
36 0 0         error_message( "Please configure github.".$fld.". in your TimeTracker config" ) unless $config->{$fld};
37 0           $args{$fld} = $config->{$fld};
38             }
39              
40             # optional
41 0 0         $args{api_uri} = $config->{api_uri} if $config->{api_uri};
42              
43 0           return Pithub->new( %args );
44             }
45              
46             before [ 'cmd_start', 'cmd_continue', 'cmd_append' ] => sub {
47             my $self = shift;
48             return unless $self->has_issue;
49              
50             my $issuename = 'issue#' . $self->issue;
51             $self->insert_tag($issuename);
52              
53             my $response = $self->github_client->issues->get(repo=>'App-TimeTracker',issue_id => $self->issue);
54             unless ($response->success) {
55             error_message("Cannot find issue %s in %s/%s",$self->issue,$self->config->{github}->@{'user','repo'});
56             return;
57             }
58             my $issue = $response->content;
59             my $name = $issue->{title};
60             #use Data::Dumper; $Data::Dumper::Maxdepth=3;$Data::Dumper::Sortkeys=1;warn Data::Dumper::Dumper $data;
61              
62             if ( defined $self->description ) {
63             $self->description( $self->description . ' ' . $name );
64             }
65             else {
66             $self->description($name);
67             }
68              
69             if ( $self->meta->does_role('App::TimeTracker::Command::Git') ) {
70             my $branch = $self->issue;
71             if ($name) {
72             $branch = $self->safe_branch_name($self->issue.' '.$name);
73             }
74             $branch=~s/_/-/g;
75             $self->branch( lc($branch) ) unless $self->branch;
76             }
77              
78             ## reopen
79             #if ($self->config->{github}{reopen} && $issue->{state} eq 'closed') {
80             # $self->_call('PUT','projects/'.$self->project_id.'/issues/'.$issue_id.'?state_event=reopen');
81             # say "reopend closed issue";
82             #}
83             #
84             ## set assignee
85             #if ($self->config->{github}{set_assignee}) {
86             # my $assignee;
87             # if ($issue->{assignees} && $issue->{assignees}[0] && $issue->{assignees}[0]{username}) {
88             # $assignee = $issue->{assignees}[0]{username};
89             # }
90             # elsif ( $issue->{assignee} && $issue->{assignee}{username}) {
91             # $assignee = $issue->{assignee}{username};
92             # }
93             #
94             # if (my $user = $self->_call('GET','user')) {
95             # if ($assignee) {
96             # if ($assignee ne $user->{username}) {
97             # warning_message("Assignee already set to ".$assignee);
98             # }
99             # }
100             # else {
101             # $self->_call('PUT','projects/'.$self->project_id.'/issues/'.$issue_id.'?assignee_id='.$user->{id});
102             # say "Assignee set to you";
103             # }
104             # }
105             # else {
106             # error_message("Cannot get user-id, thus cannot assign issue");
107             # }
108             #}
109             #
110             ## un/set labels
111             #if (my $on_start = $self->config->{github}{labels_on_start}) {
112             # my %l = map {$_ => 1} @{$issue->{labels}};
113             # if (my $add = $on_start->{add}) {
114             # foreach my $new (@$add) {
115             # $l{$new}=1;
116             # }
117             # }
118             # if (my $remove = $on_start->{remove}) {
119             # foreach my $remove (@$remove) {
120             # delete $l{$remove};
121             # }
122             # }
123             # $self->_call('PUT','projects/'.$self->project_id.'/issues/'.$issue_id.'?labels='.uri_escape(join(',',keys %l)));
124             # say "Labels are now: ".join(', ',sort keys %l);
125             #}
126             };
127              
128             sub App::TimeTracker::Data::Task::github_issue {
129 0     0 0   my $self = shift;
130 0           foreach my $tag ( @{ $self->tags } ) {
  0            
131 0 0         next unless $tag =~ /^issue#(\d+)/;
132 0           return $1;
133             }
134             }
135              
136 1     1   9 no Moose::Role;
  1         1  
  1         17  
137              
138             q{ listening to: Train noises on my way from Wien to Graz }
139              
140             __END__
141              
142             =pod
143              
144             =encoding UTF-8
145              
146             =head1 NAME
147              
148             App::TimeTracker::Command::GitHub - App::TimeTracker GitHub plugin
149              
150             =head1 VERSION
151              
152             version 1.000
153              
154             =head1 DESCRIPTION
155              
156             Connect tracker with L<GitHub|https://github.com/>.
157              
158             Using the GitHub plugin, tracker can fetch the name of an issue and use
159             it as the task's description; generate a nicely named C<git> branch
160             (if you're also using the C<Git> plugin).
161              
162             =head1 CONFIGURATION
163              
164             =head2 plugins
165              
166             Add C<GitHub> to the list of plugins.
167              
168             =head2 github
169              
170             add a hash named C<github>, containing the following keys:
171              
172             =head3 user [REQUIRED]
173              
174             Your github user name. Best stored in your global TimeTracker config file.
175              
176             =head3 token [REQUIRED]
177              
178             Your personal access token. Get it from your github settings
179             (Developer Settings, Personal access token): https://github.com/settings/tokens
180              
181             Best stored in your global TimeTracker config file.
182              
183             =head3 repo [REQUIRED]
184              
185             The name of the repository you are working on. Currently a required
186             entry to the config file, but we might upgrade it to a command line
187             param and/or try to guess it from the current working dir or your git
188             config.
189              
190             =head3 api_uri
191              
192             Optional.
193              
194             Set this to the URL of your local GitHub Enterprise installation.
195              
196             =head1 NEW COMMANDS
197              
198             No new commands
199              
200             =head1 CHANGES TO OTHER COMMANDS
201              
202             =head2 start, continue
203              
204             =head3 --issue
205              
206             ~/perl/Your-Project$ tracker start --issue 42
207              
208             If C<--issue> is set and we can find an issue with this id in your current repo
209              
210             =over
211              
212             =item * set or append the issue name in the task description ("Rev up FluxCompensator!!")
213              
214             =item * add the issue id to the tasks tags ("issue#42")
215              
216             =item * if C<Git> is also used, determine a save branch name from the issue name, and change into this branch ("42-rev-up-fluxcompensator")
217              
218             =item * TODO: assign to your user, if C<set_assignee> is set and issue is not assigned
219              
220             =item * TODO: reopen a closed issue if C<reopen> is set
221              
222             =item * TODO: modifiy the labels by adding all labels listed in C<labels_on_start.add> and removing all lables listed in C<labels_on_start.add>
223              
224             =back
225              
226             =head1 AUTHOR
227              
228             Thomas Klausner <domm@plix.at>
229              
230             =head1 COPYRIGHT AND LICENSE
231              
232             This software is copyright (c) 2020 by Thomas Klausner.
233              
234             This is free software; you can redistribute it and/or modify it under
235             the same terms as the Perl 5 programming language system itself.
236              
237             =cut