1// Copyright 2016 The go-github AUTHORS. All rights reserved.
2//
3// Use of this source code is governed by a BSD-style
4// license that can be found in the LICENSE file.
5
6package github
7
8import (
9	"context"
10	"fmt"
11	"strings"
12	"time"
13)
14
15// Timeline represents an event that occurred around an Issue or Pull Request.
16//
17// It is similar to an IssueEvent but may contain more information.
18// GitHub API docs: https://developer.github.com/v3/issues/timeline/
19type Timeline struct {
20	ID        *int64  `json:"id,omitempty"`
21	URL       *string `json:"url,omitempty"`
22	CommitURL *string `json:"commit_url,omitempty"`
23
24	// The User object that generated the event.
25	Actor *User `json:"actor,omitempty"`
26
27	// Event identifies the actual type of Event that occurred. Possible values
28	// are:
29	//
30	//     assigned
31	//       The issue was assigned to the assignee.
32	//
33	//     closed
34	//       The issue was closed by the actor. When the commit_id is present, it
35	//       identifies the commit that closed the issue using "closes / fixes #NN"
36	//       syntax.
37	//
38	//     commented
39	//       A comment was added to the issue.
40	//
41	//     committed
42	//       A commit was added to the pull request's 'HEAD' branch. Only provided
43	//       for pull requests.
44	//
45	//     cross-referenced
46	//       The issue was referenced from another issue. The 'source' attribute
47	//       contains the 'id', 'actor', and 'url' of the reference's source.
48	//
49	//     demilestoned
50	//       The issue was removed from a milestone.
51	//
52	//     head_ref_deleted
53	//       The pull request's branch was deleted.
54	//
55	//     head_ref_restored
56	//       The pull request's branch was restored.
57	//
58	//     labeled
59	//       A label was added to the issue.
60	//
61	//     locked
62	//       The issue was locked by the actor.
63	//
64	//     mentioned
65	//       The actor was @mentioned in an issue body.
66	//
67	//     merged
68	//       The issue was merged by the actor. The 'commit_id' attribute is the
69	//       SHA1 of the HEAD commit that was merged.
70	//
71	//     milestoned
72	//       The issue was added to a milestone.
73	//
74	//     referenced
75	//       The issue was referenced from a commit message. The 'commit_id'
76	//       attribute is the commit SHA1 of where that happened.
77	//
78	//     renamed
79	//       The issue title was changed.
80	//
81	//     reopened
82	//       The issue was reopened by the actor.
83	//
84	//     subscribed
85	//       The actor subscribed to receive notifications for an issue.
86	//
87	//     unassigned
88	//       The assignee was unassigned from the issue.
89	//
90	//     unlabeled
91	//       A label was removed from the issue.
92	//
93	//     unlocked
94	//       The issue was unlocked by the actor.
95	//
96	//     unsubscribed
97	//       The actor unsubscribed to stop receiving notifications for an issue.
98	//
99	Event *string `json:"event,omitempty"`
100
101	// The string SHA of a commit that referenced this Issue or Pull Request.
102	CommitID *string `json:"commit_id,omitempty"`
103	// The timestamp indicating when the event occurred.
104	CreatedAt *time.Time `json:"created_at,omitempty"`
105	// The Label object including `name` and `color` attributes. Only provided for
106	// 'labeled' and 'unlabeled' events.
107	Label *Label `json:"label,omitempty"`
108	// The User object which was assigned to (or unassigned from) this Issue or
109	// Pull Request. Only provided for 'assigned' and 'unassigned' events.
110	Assignee *User `json:"assignee,omitempty"`
111	// The Milestone object including a 'title' attribute.
112	// Only provided for 'milestoned' and 'demilestoned' events.
113	Milestone *Milestone `json:"milestone,omitempty"`
114	// The 'id', 'actor', and 'url' for the source of a reference from another issue.
115	// Only provided for 'cross-referenced' events.
116	Source *Source `json:"source,omitempty"`
117	// An object containing rename details including 'from' and 'to' attributes.
118	// Only provided for 'renamed' events.
119	Rename      *Rename      `json:"rename,omitempty"`
120	ProjectCard *ProjectCard `json:"project_card,omitempty"`
121}
122
123// Source represents a reference's source.
124type Source struct {
125	ID    *int64  `json:"id,omitempty"`
126	URL   *string `json:"url,omitempty"`
127	Actor *User   `json:"actor,omitempty"`
128	Type  *string `json:"type,omitempty"`
129	Issue *Issue  `json:"issue,omitempty"`
130}
131
132// ListIssueTimeline lists events for the specified issue.
133//
134// GitHub API docs: https://developer.github.com/v3/issues/timeline/#list-events-for-an-issue
135func (s *IssuesService) ListIssueTimeline(ctx context.Context, owner, repo string, number int, opt *ListOptions) ([]*Timeline, *Response, error) {
136	u := fmt.Sprintf("repos/%v/%v/issues/%v/timeline", owner, repo, number)
137	u, err := addOptions(u, opt)
138	if err != nil {
139		return nil, nil, err
140	}
141
142	req, err := s.client.NewRequest("GET", u, nil)
143	if err != nil {
144		return nil, nil, err
145	}
146
147	// TODO: remove custom Accept header when this API fully launches.
148	acceptHeaders := []string{mediaTypeTimelinePreview, mediaTypeProjectCardDetailsPreview}
149	req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
150
151	var events []*Timeline
152	resp, err := s.client.Do(ctx, req, &events)
153	return events, resp, err
154}
155