Skip to content

Commit

Permalink
Add PullRequestResource functionality for updating labels and comments.
Browse files Browse the repository at this point in the history
Missing from this change:
* Statuses, since this might involve more discussion on the set of statuses
  that we want to support.
* Updating from changes to the raw payloads. Unclear how we want to
  handle these at the moment. Punting on this for now.

First step for supporting tektoncd#778.

Co-authored-by: Dan Lorenc <[email protected]>
Co-authored-by: Billy Lynch <[email protected]>
  • Loading branch information
wlynch and dlorenc committed May 30, 2019
1 parent f456845 commit 0ed9abe
Show file tree
Hide file tree
Showing 29,265 changed files with 14,524,679 additions and 9,018 deletions.
The diff you're trying to view is too large. We only load the first 3000 changed files.
915 changes: 59 additions & 856 deletions Gopkg.lock

Large diffs are not rendered by default.

58 changes: 58 additions & 0 deletions cmd/pullrequest-init/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# pullrequest-init

pullrequest-init fetches pull request data from the given URL and places it in
the provided path.

This binary outputs a generic pull request object into `pr.json`, as well as
provider specific payloads.

Currently supported providers:

* GitHub

## Generic pull request payload

The payload generated by default aims to abstract the base features of any
pull request provider. Since there is no one true spec for pull requests, not
every feature may be available. The payload is output to `$PATH/pr.json` and
looks like:

```json
{
"Type": "github",
"ID": 188184279,
"Head": {
"Repo": "https:/wlynch/test.git",
"Branch": "dev",
"SHA": "9bcde245572c74329827acdcab88792ebb84d578"
},
"Base": {
"Repo": "https:/wlynch/test.git",
"Branch": "master",
"SHA": "1e80c83ed01e187669b836096335d1c8a2c57182"
},
"Comments": [
{
"Text": "test comment",
"Author": "wlynch",
"ID": 494418247,
"Raw": "/tmp/prtest/github/comments/494418247.json"
}
],
"Labels": [
{
"Text": "my-label"
}
],
"Raw": "/tmp/prtest/github/pr.json"
}
```

## GitHub

GitHub pull requests will output these additional files:

* `$PATH/github/pr.json`: The raw GitHub payload as specified by
https://developer.github.com/v3/pulls/#get-a-single-pull-request
* `$PATH/github/comments/#.json`: Comments associated to the PR as specified by
https://developer.github.com/v3/issues/comments/#get-a-single-comment
171 changes: 171 additions & 0 deletions cmd/pullrequest-init/fake_github.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
package main

import (
"encoding/json"
"fmt"
"net/http"
"strconv"

"github.com/google/go-github/github"
"github.com/gorilla/mux"
)

// key defines keys for associating data to PRs/issues in the fake server.
type key struct {
owner string
repo string
id int64
}

// FakeGitHub is a fake GitHub server for use in tests.
type FakeGitHub struct {
*mux.Router

pr map[key]*github.PullRequest
comments map[key][]*github.IssueComment
}

// NewFakeGitHub returns a new FakeGitHub.
func NewFakeGitHub() *FakeGitHub {
s := &FakeGitHub{
Router: mux.NewRouter(),
pr: make(map[key]*github.PullRequest),
comments: make(map[key][]*github.IssueComment),
}
s.HandleFunc("/repos/{owner}/{repo}/pulls/{number}", s.getPullRequest).Methods(http.MethodGet)
s.HandleFunc("/repos/{owner}/{repo}/issues/{number}/comments", s.getComments).Methods(http.MethodGet)
s.HandleFunc("/repos/{owner}/{repo}/issues/{number}/comments", s.createComment).Methods(http.MethodPost)
s.HandleFunc("/repos/{owner}/{repo}/issues/{number}/labels", s.updateLabels).Methods(http.MethodPut)

return s
}

// AddPullRequest adds the given pull request to the fake GitHub server.
func (g *FakeGitHub) AddPullRequest(pr *github.PullRequest) {
key := key{
owner: pr.GetBase().GetUser().GetLogin(),
repo: pr.GetBase().GetRepo().GetName(),
id: pr.GetID(),
}
g.pr[key] = pr
}

// AddComment adds a comment to the fake GitHub server.
func (g *FakeGitHub) AddComment(owner string, repo string, pr int64, comment *github.IssueComment) {
key := key{
owner: owner,
repo: repo,
id: pr,
}
c := g.comments[key]
if c == nil {
c = []*github.IssueComment{comment}
} else {
c = append(c, comment)
}
g.comments[key] = c
}

func (g *FakeGitHub) getPullRequest(w http.ResponseWriter, r *http.Request) {
id, err := strconv.ParseInt(mux.Vars(r)["number"], 10, 64)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
key := key{
owner: mux.Vars(r)["owner"],
repo: mux.Vars(r)["repo"],
id: id,
}

pr, ok := g.pr[key]
if !ok {
http.Error(w, fmt.Sprintf("%v not found", key), http.StatusNotFound)
return
}

if err := json.NewEncoder(w).Encode(pr); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}

func (g *FakeGitHub) getComments(w http.ResponseWriter, r *http.Request) {
id, err := strconv.ParseInt(mux.Vars(r)["number"], 10, 64)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
key := key{
owner: mux.Vars(r)["owner"],
repo: mux.Vars(r)["repo"],
id: id,
}
comments, ok := g.comments[key]
if !ok {
comments = []*github.IssueComment{}
}
if err := json.NewEncoder(w).Encode(comments); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}

func (g *FakeGitHub) createComment(w http.ResponseWriter, r *http.Request) {
id, err := strconv.ParseInt(mux.Vars(r)["number"], 10, 64)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
key := key{
owner: mux.Vars(r)["owner"],
repo: mux.Vars(r)["repo"],
id: id,
}

c := new(github.IssueComment)
if err := json.NewDecoder(r.Body).Decode(c); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
comments, ok := g.comments[key]
if !ok {
comments = []*github.IssueComment{}
}
c.ID = github.Int64(int64(len(comments) + 1))
g.comments[key] = append(comments, c)

w.WriteHeader(http.StatusOK)
}

func (g *FakeGitHub) updateLabels(w http.ResponseWriter, r *http.Request) {
id, err := strconv.ParseInt(mux.Vars(r)["number"], 10, 64)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
key := key{
owner: mux.Vars(r)["owner"],
repo: mux.Vars(r)["repo"],
id: id,
}
pr, ok := g.pr[key]
if !ok {
http.Error(w, "pull request not found", http.StatusNotFound)
return
}

payload := []string{}
if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
pr.Labels = make([]*github.Label, 0, len(payload))
for _, l := range payload {
pr.Labels = append(pr.Labels, &github.Label{
Name: github.String(l),
})
}

w.WriteHeader(http.StatusOK)
}
Loading

0 comments on commit 0ed9abe

Please sign in to comment.