File Coverage

lib/App/TimeTracker/Command/Gitlab.pm
Criterion Covered Total %
statement 23 49 46.9
branch 0 10 0.0
condition 0 8 0.0
subroutine 8 12 66.6
pod 0 1 0.0
total 31 80 38.7


line stmt bran cond sub pod time code
1             package App::TimeTracker::Command::Gitlab;
2 1     1   517 use strict;
  1         1  
  1         26  
3 1     1   3 use warnings;
  1         1  
  1         28  
4 1     1   21 use 5.010;
  1         10  
5              
6             # ABSTRACT: App::TimeTracker Gitlab plugin
7 1     1   441 use App::TimeTracker::Utils qw(error_message warning_message);
  1         7438  
  1         71  
8              
9             our $VERSION = "1.002";
10              
11 1     1   398 use Moose::Role;
  1         311047  
  1         4  
12 1     1   4769 use HTTP::Tiny;
  1         37477  
  1         38  
13 1     1   7 use JSON::XS qw(encode_json decode_json);
  1         2  
  1         555  
14              
15             has 'issue' => (
16             is => 'rw',
17             isa => 'Str',
18             documentation => 'gitlab issue',
19             predicate => 'has_issue'
20             );
21              
22             has 'gitlab_client' => (
23             is => 'rw',
24             isa => 'Maybe[HTTP::Tiny]',
25             lazy_build => 1,
26             traits => ['NoGetopt'],
27             );
28              
29             sub _build_gitlab_client {
30 0     0     my $self = shift;
31 0           my $config = $self->config->{gitlab};
32              
33 0 0 0       unless ( $config->{url} && $config->{token} ) {
34 0           error_message(
35             "Please configure Gitlab in your TimeTracker config (needs url & token)"
36             );
37 0           return;
38             }
39              
40             return HTTP::Tiny->new(default_headers=>{
41             'PRIVATE-TOKEN'=> $self->config->{gitlab}{token},
42 0           });
43             }
44              
45             has 'project_id' => (
46             is=>'ro',
47             isa=>'Str',
48             documentation=>'The ID or namespace/name of this project',
49             lazy_build=>1,
50             );
51              
52             sub _build_project_id {
53 0     0     my $self = shift;
54 0 0         return $self->config->{gitlab}{project_id} if $self->config->{gitlab}{project_id};
55 0           my $name = $self->config->{project};
56 0   0       my $namespace = $self->config->{gitlab}{namespace} || '' ;
57 0 0 0       if ($name && $namespace) {
58 0           return join('%2F',$namespace, $name);
59             }
60 0           error_message("Please set either project_id, or project and namespace");
61             return
62 0           }
63              
64             before [ 'cmd_start', 'cmd_continue', 'cmd_append' ] => sub {
65             my $self = shift;
66             return unless $self->has_issue;
67              
68             my $issuename = 'issue#' . $self->issue;
69             $self->insert_tag($issuename);
70              
71             my $issues = $self->_call('GET','projects/'.$self->project_id.'/issues?iid='.$self->issue);
72             my $issue = $issues->[0];
73             unless ($issue) {
74             error_message("Cannot find issue %s in %s",$self->issue,$self->project_id);
75             return;
76             }
77             my $name = $issue->{title};
78              
79             if ( defined $self->description ) {
80             $self->description( $self->description . ' ' . $name );
81             }
82             else {
83             $self->description($name);
84             }
85              
86             if ( $self->meta->does_role('App::TimeTracker::Command::Git') ) {
87             my $branch = $self->issue;
88             if ($name) {
89             $branch = $self->safe_branch_name($self->issue.' '.$name);
90             }
91             $branch=~s/_/-/g;
92             $self->branch( lc($branch) ) unless $self->branch;
93             }
94              
95             # TODO set assignee
96              
97             };
98              
99             #after [ 'cmd_start', 'cmd_continue', 'cmd_append' ] => sub {
100             # my $self = shift;
101             # TODO: do we want to do something after stop?
102             #};
103              
104             sub _call {
105 0     0     my ($self,$method, $endpoint, $args) = @_;
106              
107 0           my $url = $self->config->{gitlab}{url}.'/api/v3/'.$endpoint;
108 0           my $res = $self->gitlab_client->request($method,$url);
109              
110 0 0         if ($res->{success}) {
111 0           my $data = decode_json($res->{content});
112 0           return $data;
113             }
114 0           error_message(join(" ",$res->{status},$res->{reason}));
115             }
116              
117             sub App::TimeTracker::Data::Task::gitlab_issue {
118 0     0 0   my $self = shift;
119 0           foreach my $tag ( @{ $self->tags } ) {
  0            
120 0 0         next unless $tag =~ /^issue#(\d+)/;
121 0           return $1;
122             }
123             }
124              
125 1     1   6 no Moose::Role;
  1         1  
  1         10  
126             1;
127              
128             __END__
129              
130             =pod
131              
132             =encoding UTF-8
133              
134             =head1 NAME
135              
136             App::TimeTracker::Command::Gitlab - App::TimeTracker Gitlab plugin
137              
138             =head1 VERSION
139              
140             version 1.002
141              
142             =head1 DESCRIPTION
143              
144             Connect tracker with L<Gitlab|https://about.gitlab.com/>.
145              
146             Using the Gitlab plugin, tracker can fetch the name of an issue and use
147             it as the task's description; generate a nicely named C<git> branch
148             (if you're also using the C<Git> plugin).
149              
150             Planned but not implemented: Adding yourself as the assignee.
151              
152             =head1 CONFIGURATION
153              
154             =head2 plugins
155              
156             Add C<Gitlab> to the list of plugins.
157              
158             =head2 gitlab
159              
160             add a hash named C<gitlab>, containing the following keys:
161              
162             =head3 url [REQUIRED]
163              
164             The base URL of your gitlab instance, eg C<https://gitlab.example.com>
165              
166             =head3 token [REQUIRED]
167              
168             Your personal access token. Get it from your gitlab profile page. For
169             now you probably want to use a token with unlimited expiry time. We
170             might implement a way to fetch a shortlived token (like in the Trello
171             plugin), but gitlab does not support installed-apps OAuth2.
172              
173             =head3 namespace [REQUIRED]
174              
175             The C<namespace> of the current project, eg C<validad> if this is your repo: C<https://gitlab.example.com/validad/App-TimeTracker-Gitlab>
176              
177             =head1 NEW COMMANDS
178              
179             No new commands
180              
181             =head1 CHANGES TO OTHER COMMANDS
182              
183             =head2 start, continue
184              
185             =head3 --issue
186              
187             ~/perl/Your-Project$ tracker start --issue 42
188              
189             If C<--issue> is set and we can find an issue with this id in your current repo
190              
191             =over
192              
193             =item * set or append the issue name in the task description ("Rev up FluxCompensator!!")
194              
195             =item * add the issue id to the tasks tags ("issue#42")
196              
197             =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")
198              
199             =back
200              
201             =head1 AUTHOR
202              
203             Thomas Klausner <domm@cpan.org>
204              
205             =head1 COPYRIGHT AND LICENSE
206              
207             This software is copyright (c) 2016 by Thomas Klausner.
208              
209             This is free software; you can redistribute it and/or modify it under
210             the same terms as the Perl 5 programming language system itself.
211              
212             =cut