1package Pithub::Issues;
2our $AUTHORITY = 'cpan:PLU';
3our $VERSION = '0.01036';
4# ABSTRACT: Github v3 Issues API
5
6use Moo;
7use Carp qw( croak );
8use Pithub::Issues::Assignees;
9use Pithub::Issues::Comments;
10use Pithub::Issues::Events;
11use Pithub::Issues::Labels;
12use Pithub::Issues::Milestones;
13extends 'Pithub::Base';
14
15
16sub assignees {
17    return shift->_create_instance('Pithub::Issues::Assignees', @_);
18}
19
20
21sub comments {
22    return shift->_create_instance('Pithub::Issues::Comments', @_);
23}
24
25
26sub create {
27    my ( $self, %args ) = @_;
28    croak 'Missing key in parameters: data (hashref)' unless ref $args{data} eq 'HASH';
29    $self->_validate_user_repo_args( \%args );
30    return $self->request(
31        method => 'POST',
32        path   => sprintf( '/repos/%s/%s/issues', delete $args{user}, delete $args{repo} ),
33        %args,
34    );
35}
36
37
38sub events {
39    return shift->_create_instance('Pithub::Issues::Events', @_);
40}
41
42
43sub get {
44    my ( $self, %args ) = @_;
45    croak 'Missing key in parameters: issue_id' unless $args{issue_id};
46    $self->_validate_user_repo_args( \%args );
47    return $self->request(
48        method => 'GET',
49        path   => sprintf( '/repos/%s/%s/issues/%s', delete $args{user}, delete $args{repo}, delete $args{issue_id} ),
50        %args,
51    );
52}
53
54
55sub labels {
56    return shift->_create_instance('Pithub::Issues::Labels', @_);
57}
58
59
60sub list {
61    my ( $self, %args ) = @_;
62    $self->_get_user_repo_args( \%args );
63    if ( $args{user} && $args{repo} ) {
64        return $self->request(
65            method => 'GET',
66            path   => sprintf( '/repos/%s/%s/issues', delete $args{user}, delete $args{repo} ),
67            %args,
68        );
69    }
70    return $self->request(
71        method => 'GET',
72        path   => sprintf('/issues'),
73        %args,
74    );
75}
76
77
78sub milestones {
79    return shift->_create_instance('Pithub::Issues::Milestones', @_);
80}
81
82
83sub update {
84    my ( $self, %args ) = @_;
85    croak 'Missing key in parameters: issue_id' unless $args{issue_id};
86    croak 'Missing key in parameters: data (hashref)' unless ref $args{data} eq 'HASH';
87    $self->_validate_user_repo_args( \%args );
88    return $self->request(
89        method => 'PATCH',
90        path   => sprintf( '/repos/%s/%s/issues/%s', delete $args{user}, delete $args{repo}, delete $args{issue_id} ),
91        %args,
92    );
93}
94
951;
96
97__END__
98
99=pod
100
101=encoding UTF-8
102
103=head1 NAME
104
105Pithub::Issues - Github v3 Issues API
106
107=head1 VERSION
108
109version 0.01036
110
111=head1 METHODS
112
113=head2 assignees
114
115Provides access to L<Pithub::Issues::Assignees>.
116
117=head2 comments
118
119Provides access to L<Pithub::Issues::Comments>.
120
121=head2 create
122
123=over
124
125=item *
126
127Create an issue
128
129    POST /repos/:user/:repo/issues
130
131Parameters:
132
133=over
134
135=item *
136
137B<user>: mandatory string
138
139=item *
140
141B<repo>: mandatory string
142
143=item *
144
145B<data>: mandatory hashref, having following keys:
146
147=over
148
149=item *
150
151B<title>: mandatory string
152
153=item *
154
155B<body>: optional string
156
157=item *
158
159B<assignee>: optional string - Login for the user that this issue
160should be assigned to.
161
162=item *
163
164B<milestone>: optional number - Milestone to associate this issue
165with.
166
167=item *
168
169B<labels>: optional arrayref of strings - Labels to associate with this
170issue.
171
172=back
173
174=back
175
176Examples:
177
178    my $i = Pithub::Issues->new;
179    my $result = $i->create(
180        user => 'plu',
181        repo => 'Pithub',
182        data => {
183            assignee  => 'octocat',
184            body      => "I'm having a problem with this.",
185            labels    => [ 'Label1', 'Label2' ],
186            milestone => 1,
187            title     => 'Found a bug'
188        }
189    );
190
191Response: B<Status: 201 Created>
192
193    {
194        "url": "https://api.github.com/repos/octocat/Hello-World/issues/1",
195        "html_url": "https://github.com/octocat/Hello-World/issues/1",
196        "number": 1347,
197        "state": "open",
198        "title": "Found a bug",
199        "body": "I'm having a problem with this.",
200        "user": {
201            "login": "octocat",
202            "id": 1,
203            "gravatar_url": "https://github.com/images/error/octocat_happy.gif",
204            "url": "https://api.github.com/users/octocat"
205        },
206        "labels": [
207        {
208            "url": "https://api.github.com/repos/octocat/Hello-World/labels/bug",
209            "name": "bug",
210            "color": "f29513"
211        }
212        ],
213        "assignee": {
214            "login": "octocat",
215            "id": 1,
216            "gravatar_url": "https://github.com/images/error/octocat_happy.gif",
217            "url": "https://api.github.com/users/octocat"
218        },
219        "milestone": {
220            "url": "https://api.github.com/repos/octocat/Hello-World/milestones/1",
221            "number": 1,
222            "state": "open",
223            "title": "v1.0",
224            "description": "",
225            "creator": {
226                "login": "octocat",
227                "id": 1,
228                "gravatar_url": "https://github.com/images/error/octocat_happy.gif",
229                "url": "https://api.github.com/users/octocat"
230            },
231            "open_issues": 4,
232            "closed_issues": 8,
233            "created_at": "2011-04-10T20:09:31Z",
234            "due_on": null
235        },
236        "comments": 0,
237        "pull_request": {
238            "html_url": "https://github.com/octocat/Hello-World/issues/1",
239            "diff_url": "https://github.com/octocat/Hello-World/issues/1.diff",
240            "patch_url": "https://github.com/octocat/Hello-World/issues/1.patch"
241        },
242        "closed_at": null,
243        "created_at": "2011-04-22T13:33:48Z",
244        "updated_at": "2011-04-22T13:33:48Z"
245    }
246
247=back
248
249=head2 events
250
251Provides access to L<Pithub::Issues::Events>.
252
253=head2 get
254
255=over
256
257=item *
258
259Get a single issue
260
261    GET /repos/:user/:repo/issues/:id
262
263Parameters:
264
265=over
266
267=item *
268
269B<user>: mandatory string
270
271=item *
272
273B<repo>: mandatory string
274
275=item *
276
277B<issue_id>: mandatory integer
278
279=back
280
281Examples:
282
283    my $i = Pithub::Issues->new;
284    my $result = $i->get(
285        user => 'plu',
286        repo => 'Pithub',
287        issue_id => 1,
288    );
289
290Response: B<Status: 200 OK>
291
292    {
293        "url": "https://api.github.com/repos/octocat/Hello-World/issues/1",
294        "html_url": "https://github.com/octocat/Hello-World/issues/1",
295        "number": 1347,
296        "state": "open",
297        "title": "Found a bug",
298        "body": "I'm having a problem with this.",
299        "user": {
300            "login": "octocat",
301            "id": 1,
302            "gravatar_url": "https://github.com/images/error/octocat_happy.gif",
303            "url": "https://api.github.com/users/octocat"
304        },
305        "labels": [
306        {
307            "url": "https://api.github.com/repos/octocat/Hello-World/labels/bug",
308            "name": "bug",
309            "color": "f29513"
310        }
311        ],
312        "assignee": {
313            "login": "octocat",
314            "id": 1,
315            "gravatar_url": "https://github.com/images/error/octocat_happy.gif",
316            "url": "https://api.github.com/users/octocat"
317        },
318        "milestone": {
319            "url": "https://api.github.com/repos/octocat/Hello-World/milestones/1",
320            "number": 1,
321            "state": "open",
322            "title": "v1.0",
323            "description": "",
324            "creator": {
325                "login": "octocat",
326                "id": 1,
327                "gravatar_url": "https://github.com/images/error/octocat_happy.gif",
328                "url": "https://api.github.com/users/octocat"
329            },
330            "open_issues": 4,
331            "closed_issues": 8,
332            "created_at": "2011-04-10T20:09:31Z",
333            "due_on": null
334        },
335        "comments": 0,
336        "pull_request": {
337            "html_url": "https://github.com/octocat/Hello-World/issues/1",
338            "diff_url": "https://github.com/octocat/Hello-World/issues/1.diff",
339            "patch_url": "https://github.com/octocat/Hello-World/issues/1.patch"
340        },
341        "closed_at": null,
342        "created_at": "2011-04-22T13:33:48Z",
343        "updated_at": "2011-04-22T13:33:48Z"
344    }
345
346=back
347
348=head2 labels
349
350Provides access to L<Pithub::Issues::Labels>.
351
352=head2 list
353
354=over
355
356=item *
357
358List the issues of the authenticated user
359
360    GET /issues
361
362This API call can be influenced via the C<< params >>
363hashref with following parameters:
364
365=over
366
367=item *
368
369B<filter>: one of the following:
370
371=over
372
373=item *
374
375B<assigned>: Issues assigned to you (default)
376
377=item *
378
379B<created>: Issues created by you
380
381=item *
382
383B<mentioned>: Issues mentioning you
384
385=item *
386
387B<subscribed>: Issues you're subscribed to updates for
388
389=back
390
391=item *
392
393B<state>: one of the following:
394
395=over
396
397=item *
398
399B<open> (default)
400
401=item *
402
403B<closed>
404
405=back
406
407=item *
408
409B<labels>: String list of comma separated Label names.
410Example: C<< bug,ui,@high >>
411
412=item *
413
414B<sort>: one of the following:
415
416=over
417
418=item *
419
420B<created> (default)
421
422=item *
423
424B<updated>
425
426=item *
427
428B<comments>
429
430=back
431
432=item *
433
434B<direction>: one of the following:
435
436=over
437
438=item *
439
440B<asc>
441
442=item *
443
444B<desc> (default)
445
446=back
447
448=item *
449
450B<since>: optional string of a timestamp in ISO 8601 format: YYYY-MM-DDTHH:MM:SSZ
451
452=back
453
454Examples:
455
456    my $i      = Pithub::Issues->new;
457    my $result = $i->list(
458        params => {
459            filter    => 'assigned',
460            state     => 'open',
461            labels    => 'bug',
462            sort      => 'updated',
463            direction => 'asc',
464        }
465    );
466
467Response: B<Status: 200 OK>
468
469    [
470        {
471            "url": "https://api.github.com/repos/octocat/Hello-World/issues/1",
472            "html_url": "https://github.com/octocat/Hello-World/issues/1",
473            "number": 1347,
474            "state": "open",
475            "title": "Found a bug",
476            "body": "I'm having a problem with this.",
477            "user": {
478                "login": "octocat",
479                "id": 1,
480                "gravatar_url": "https://github.com/images/error/octocat_happy.gif",
481                "url": "https://api.github.com/users/octocat"
482            },
483            "labels": [
484            {
485                "url": "https://api.github.com/repos/octocat/Hello-World/labels/bug",
486                "name": "bug",
487                "color": "f29513"
488            }
489            ],
490            "assignee": {
491                "login": "octocat",
492                "id": 1,
493                "gravatar_url": "https://github.com/images/error/octocat_happy.gif",
494                "url": "https://api.github.com/users/octocat"
495            },
496            "milestone": {
497                "url": "https://api.github.com/repos/octocat/Hello-World/milestones/1",
498                "number": 1,
499                "state": "open",
500                "title": "v1.0",
501                "description": "",
502                "creator": {
503                    "login": "octocat",
504                    "id": 1,
505                    "gravatar_url": "https://github.com/images/error/octocat_happy.gif",
506                    "url": "https://api.github.com/users/octocat"
507                },
508                "open_issues": 4,
509                "closed_issues": 8,
510                "created_at": "2011-04-10T20:09:31Z",
511                "due_on": null
512            },
513            "comments": 0,
514            "pull_request": {
515                "html_url": "https://github.com/octocat/Hello-World/issues/1",
516                "diff_url": "https://github.com/octocat/Hello-World/issues/1.diff",
517                "patch_url": "https://github.com/octocat/Hello-World/issues/1.patch"
518            },
519            "closed_at": null,
520            "created_at": "2011-04-22T13:33:48Z",
521            "updated_at": "2011-04-22T13:33:48Z"
522        }
523    ]
524
525=item *
526
527List issues for a repository
528
529    GET /repos/:user/:repo/issues
530
531Parameters:
532
533=over
534
535=item *
536
537B<user>: mandatory string
538
539=item *
540
541B<repo>: mandatory string
542
543=back
544
545This API call can be influenced via the C<< params >>
546hashref with following parameters:
547
548=over
549
550=item *
551
552B<milestone>: one of the following:
553
554=over
555
556=item *
557
558C<< Integer >> Milestone number
559
560=item *
561
562C<< none >> for Issues with no Milestone
563
564=item *
565
566C<< * >> for Issues with any Milestone
567
568=back
569
570=item *
571
572B<state>: one of the following:
573
574=over
575
576=item *
577
578B<open> (default)
579
580=item *
581
582B<closed>
583
584=back
585
586=item *
587
588B<assignee>: one of the following:
589
590=over
591
592=item *
593
594C<< String >> User login
595
596=item *
597
598C<< none >> for Issues with no assigned User
599
600=item *
601
602C<< * >> for Issues with any assigned User
603
604=back
605
606=item *
607
608B<mentioned>: String User login
609
610=item *
611
612B<labels>: String list of comma separated Label names.
613Example: C<< bug,ui,@high >>
614
615=item *
616
617B<sort>: one of the following:
618
619=over
620
621=item *
622
623B<created> (default)
624
625=item *
626
627B<updated>
628
629=item *
630
631B<comments>
632
633=back
634
635=item *
636
637B<direction>: one of the following:
638
639=over
640
641=item *
642
643B<asc>
644
645=item *
646
647B<desc> (default)
648
649=back
650
651=item *
652
653B<since>: optional string of a timestamp in ISO 8601 format: YYYY-MM-DDTHH:MM:SSZ
654
655=back
656
657Examples:
658
659    my $i      = Pithub::Issues->new;
660    my $result = $i->list(
661        user    => 'plu',
662        repo    => 'Pithub',
663        params => {
664            milestone => 42,
665            state     => 'open',
666            labels    => 'bug',
667            sort      => 'updated',
668            direction => 'asc',
669        }
670    );
671
672Response: B<Status: 200 OK>
673
674    [
675        {
676            "url": "https://api.github.com/repos/octocat/Hello-World/issues/1",
677            "html_url": "https://github.com/octocat/Hello-World/issues/1",
678            "number": 1347,
679            "state": "open",
680            "title": "Found a bug",
681            "body": "I'm having a problem with this.",
682            "user": {
683                "login": "octocat",
684                "id": 1,
685                "gravatar_url": "https://github.com/images/error/octocat_happy.gif",
686                "url": "https://api.github.com/users/octocat"
687            },
688            "labels": [
689            {
690                "url": "https://api.github.com/repos/octocat/Hello-World/labels/bug",
691                "name": "bug",
692                "color": "f29513"
693            }
694            ],
695            "assignee": {
696                "login": "octocat",
697                "id": 1,
698                "gravatar_url": "https://github.com/images/error/octocat_happy.gif",
699                "url": "https://api.github.com/users/octocat"
700            },
701            "milestone": {
702                "url": "https://api.github.com/repos/octocat/Hello-World/milestones/1",
703                "number": 1,
704                "state": "open",
705                "title": "v1.0",
706                "description": "",
707                "creator": {
708                    "login": "octocat",
709                    "id": 1,
710                    "gravatar_url": "https://github.com/images/error/octocat_happy.gif",
711                    "url": "https://api.github.com/users/octocat"
712                },
713                "open_issues": 4,
714                "closed_issues": 8,
715                "created_at": "2011-04-10T20:09:31Z",
716                "due_on": null
717            },
718            "comments": 0,
719            "pull_request": {
720                "html_url": "https://github.com/octocat/Hello-World/issues/1",
721                "diff_url": "https://github.com/octocat/Hello-World/issues/1.diff",
722                "patch_url": "https://github.com/octocat/Hello-World/issues/1.patch"
723            },
724            "closed_at": null,
725            "created_at": "2011-04-22T13:33:48Z",
726            "updated_at": "2011-04-22T13:33:48Z"
727        }
728    ]
729
730=back
731
732=head2 milestones
733
734Provides access to L<Pithub::Issues::Milestones>.
735
736=head2 update
737
738=over
739
740=item *
741
742Edit an issue
743
744    PATCH /repos/:user/:repo/issues/:id
745
746Parameters:
747
748=over
749
750=item *
751
752B<user>: mandatory string
753
754=item *
755
756B<repo>: mandatory string
757
758=item *
759
760B<data>: mandatory hashref, having following keys:
761
762=over
763
764=item *
765
766B<title>: mandatory string
767
768=item *
769
770B<body>: optional string
771
772=item *
773
774B<assignee>: optional string - Login for the user that this issue
775should be assigned to.
776
777=item *
778
779B<milestone>: optional number - Milestone to associate this issue
780with.
781
782=item *
783
784B<labels>: optional arrayref of strings - Labels to associate with
785this issue. Pass one or more Labels to replace the set of Labels
786on this Issue. Send an empty arrayref (C<< [] >>) to clear all
787Labels from the Issue.
788
789=back
790
791=back
792
793Examples:
794
795    my $i = Pithub::Issues->new;
796    my $result = $i->update(
797        user     => 'plu',
798        repo     => 'Pithub',
799        issue_id => 1,
800        data     => {
801            assignee  => 'octocat',
802            body      => "I'm having a problem with this.",
803            labels    => [ 'Label1', 'Label2' ],
804            milestone => 1,
805            state     => 'open',
806            title     => 'Found a bug'
807        }
808    );
809
810=back
811
812=head1 AUTHOR
813
814Johannes Plunien <plu@cpan.org>
815
816=head1 COPYRIGHT AND LICENSE
817
818This software is copyright (c) 2011-2019 by Johannes Plunien.
819
820This is free software; you can redistribute it and/or modify it under
821the same terms as the Perl 5 programming language system itself.
822
823=cut
824