Repository: google/go-github
Pull request #1139 (2019-03-29 19:56:35)

Support content attachments api

codecov[bot]: # [Codecov](https://codecov.io/gh/google/go-github/pull/1139?src=pr&el=h1) Report
> Merging [#1139](https://codecov.io/gh/google/go-github/pull/1139?src=pr&el=desc) into [master](https://codecov.io/gh/google/go-github/commit/14c49e15859cee6aa620bfac2dad50899379c20e?src=pr&el=desc) will **decrease** coverage by `<.01%`.
> The diff coverage is `66.66%`.

[![Impacted file tree graph](https://codecov.io/gh/google/go-github/pull/1139/graphs/tree.svg?width=650&token=EgYjGjZlI0&height=150&src=pr)](https://codecov.io/gh/google/go-github/pull/1139?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master    #1139      +/-   ##
==========================================
- Coverage   70.18%   70.17%   -0.01%     
==========================================
  Files          84       84              
  Lines        5792     5804      +12     
==========================================
+ Hits         4065     4073       +8     
- Misses        947      949       +2     
- Partials      780      782       +2
```


| [Impacted Files](https://codecov.io/gh/google/go-github/pull/1139?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [github/apps.go](https://codecov.io/gh/google/go-github/pull/1139/diff?src=pr&el=tree#diff-Z2l0aHViL2FwcHMuZ28=) | `65.51% <66.66%> (+0.18%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/google/go-github/pull/1139?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/google/go-github/pull/1139?src=pr&el=footer). Last update [14c49e1...66dee44](https://codecov.io/gh/google/go-github/pull/1139?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

nadavkaner: @gmlewis Done 👍🏼

Patch:
diff --git a/AUTHORS b/AUTHORS
index 1bde5b1f..c738851a 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -54,6 +54,7 @@ Charlie Yan <charlieyan08@gmail.com>
 Chris King <chriskingnet@gmail.com>
 Chris Roche <chris@vsco.co>
 Chris Schaefer <chris@dtzq.com>
+chrisforrette <chris@chrisforrette.com>
 Christoph Sassenberg <defsprite@gmail.com>
 Colin Misare <github.com/cmisare>
 Craig Peterson <cpeterson@stackoverflow.com>
@@ -117,6 +118,7 @@ Joan Saum <joan.saum@epitech.eu>
 Joe Tsai <joetsai@digital-static.net>
 John Barton <jrbarton@gmail.com>
 John Engelman <john.r.engelman@gmail.com>
+Jordan Brockopp <jdbro94@gmail.com>
 Jordan Sussman <jordansail22@gmail.com>
 Joshua Bezaleel Abednego <joshua.bezaleel@gmail.com>
 JP Phillips <jonphill9@gmail.com>
@@ -137,6 +139,7 @@ Kookheon Kwon <kucuny@gmail.com>
 Krzysztof Kowalczyk <kkowalczyk@gmail.com>
 Kshitij Saraogi <KshitijSaraogi@gmail.com>
 kyokomi <kyoko1220adword@gmail.com>
+Liam Galvin <liam@liam-galvin.co.uk>
 Lovro Mažgon <lovro.mazgon@gmail.com>
 Lucas Alcantara <lucasalcantaraf@gmail.com>
 Luke Evers <me@lukevers.com>
@@ -180,6 +183,7 @@ Rackspace US, Inc.
 Radek Simko <radek.simko@gmail.com>
 Radliński Ignacy <radlinsk@student.agh.edu.pl>
 Rajendra arora <rajendraarora16@yahoo.com>
+Ranbir Singh <binkkatal.r@gmail.com>
 RaviTeja Pothana <ravi-teja@live.com>
 rc1140 <jameel@republiccommandos.co.za>
 Red Hat, Inc.
@@ -214,6 +218,7 @@ Thomas Bruyelle <thomas.bruyelle@gmail.com>
 Timothée Peignier <timothee.peignier@tryphon.org>
 Trey Tacon <ttacon@gmail.com>
 ttacon <ttacon@gmail.com>
+Vaibhav Singh <vaibhav.singh.14cse@bml.edu.in>
 Varadarajan Aravamudhan <varadaraajan@gmail.com>
 Victor Castell <victor@victorcastell.com>
 Victor Vrantchan <vrancean+github@gmail.com>
@@ -225,5 +230,6 @@ xibz <impactbchang@gmail.com>
 Yann Malet <yann.malet@gmail.com>
 Yannick Utard <yannickutard@gmail.com>
 Yicheng Qin <qycqycqycqycqyc@gmail.com>
+Yosuke Akatsuka <yosuke.akatsuka@access-company.com>
 Yumikiyo Osanai <yumios.art@gmail.com>
 Zach Latta <zach@zachlatta.com>
diff --git a/github/apps.go b/github/apps.go
index ae3aabda..1ad9a981 100644
--- a/github/apps.go
+++ b/github/apps.go
@@ -62,6 +62,13 @@ type Installation struct {
 	UpdatedAt           *Timestamp               `json:"updated_at,omitempty"`
 }
 
+// Attachment represents a GitHub Apps attachment.
+type Attachment struct {
+	ID    *int64  `json:"id,omitempty"`
+	Title *string `json:"title,omitempty"`
+	Body  *string `json:"body,omitempty"`
+}
+
 func (i Installation) String() string {
 	return Stringify(i)
 }
@@ -183,6 +190,29 @@ func (s *AppsService) CreateInstallationToken(ctx context.Context, id int64) (*I
 	return t, resp, nil
 }
 
+// Create a new attachment on user comment containing a url.
+//
+// GitHub API docs: https://developer.github.com/v3/apps/#create-a-content-attachment
+func (s *AppsService) CreateAttachment(ctx context.Context, contentReferenceID int64, title, body string) (*Attachment, *Response, error) {
+	u := fmt.Sprintf("content_references/%v/attachments", contentReferenceID)
+	payload := &Attachment{Title: String(title), Body: String(body)}
+	req, err := s.client.NewRequest("POST", u, payload)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	// TODO: remove custom Accept headers when APIs fully launch.
+	req.Header.Set("Accept", mediaTypeReactionsPreview)
+
+	m := &Attachment{}
+	resp, err := s.client.Do(ctx, req, m)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return m, resp, nil
+}
+
 // FindOrganizationInstallation finds the organization's installation information.
 //
 // GitHub API docs: https://developer.github.com/v3/apps/#find-organization-installation
diff --git a/github/github-accessors.go b/github/github-accessors.go
index 10015590..d8ca5deb 100644
--- a/github/github-accessors.go
+++ b/github/github-accessors.go
@@ -188,6 +188,30 @@ func (a *App) GetUpdatedAt() time.Time {
 	return *a.UpdatedAt
 }
 
+// GetBody returns the Body field if it's non-nil, zero value otherwise.
+func (a *Attachment) GetBody() string {
+	if a == nil || a.Body == nil {
+		return ""
+	}
+	return *a.Body
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (a *Attachment) GetID() int64 {
+	if a == nil || a.ID == nil {
+		return 0
+	}
+	return *a.ID
+}
+
+// GetTitle returns the Title field if it's non-nil, zero value otherwise.
+func (a *Attachment) GetTitle() string {
+	if a == nil || a.Title == nil {
+		return ""
+	}
+	return *a.Title
+}
+
 // GetApp returns the App field.
 func (a *Authorization) GetApp() *AuthorizationApp {
 	if a == nil {


Test patch:
diff --git a/github/apps_test.go b/github/apps_test.go
index a594eab3..8456662b 100644
--- a/github/apps_test.go
+++ b/github/apps_test.go
@@ -185,6 +185,28 @@ func TestAppsService_CreateInstallationToken(t *testing.T) {
 	}
 }
 
+func TestAppsService_CreateAttachement(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/content_references/11/attachments", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "POST")
+		testHeader(t, r, "Accept", mediaTypeReactionsPreview)
+
+		w.WriteHeader(http.StatusOK)
+		w.Write([]byte(`{"id":1,"title":"title1","body":"body1"}`))
+	})
+
+	got, _, err := client.Apps.CreateAttachment(context.Background(), 11, "title1", "body1")
+	if err != nil {
+		t.Errorf("CreateAttachment returned error: %v", err)
+	}
+
+	want := &Attachment{ID: Int64(1), Title: String("title1"), Body: String("body1")}
+	if !reflect.DeepEqual(got, want) {
+		t.Errorf("CreateAttachment = %+v, want %+v", got, want)
+	}
+}
 func TestAppsService_FindOrganizationInstallation(t *testing.T) {
 	client, mux, _, teardown := setup()
 	defer teardown()