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