Skip to content

Commit

Permalink
Merge pull request #8 from thefederationinfo/opt_in-out
Browse files Browse the repository at this point in the history
Implement opt-in/out for pull requests
  • Loading branch information
Lukas Matt authored Mar 18, 2018
2 parents 6000f83 + 02ae6c5 commit 9a9c09c
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 9 deletions.
13 changes: 13 additions & 0 deletions frontend.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,19 @@ func resultPage(w http.ResponseWriter, r *http.Request) {
Secret: secret,
}

// set the repo to opt-in
if strings.ToUpper(r.URL.Query().Get("optin")) == "ON" {
repo.OptIn = true
}
// define custom opt-in flag
if r.URL.Query().Get("optinFlag") != "" {
repo.OptInFlag = r.URL.Query().Get("optinFlag")
}
// define custom opt-out flag
if r.URL.Query().Get("optoutFlag") != "" {
repo.OptOutFlag = r.URL.Query().Get("optoutFlag")
}

name := "web"
hook := github.Hook{
Name: &name, Events: []string{"pull_request"},
Expand Down
3 changes: 3 additions & 0 deletions repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ type Repo struct {
Slug string
Token string
Secret string
OptIn bool
OptInFlag string `gorm:"default:'ci'"`
OptOutFlag string `gorm:"default:'ci skip'"`
}

type Repos []Repo
23 changes: 23 additions & 0 deletions templates/auth.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,29 @@
<input type="text" class="form-control" id="repoInput" name="repo" aria-describedby="repoHelp" placeholder="Enter your project slug">
<small id="repoHelp" class="form-text text-muted">Your project slug is the Github user- and repository name separated by a slash e.g. ganggo/federation</small>
</div>
<div class="form-check mb-3">
<input type="checkbox" class="form-check-input" id="optinInput" name="optin" describedby="optinHelp">
<label class="form-check-label" for="optinInput">Check if you want to opt-in on a new test</label>
<small id="optinHelp" class="form-text text-muted">
That would mean that tests are triggered if you specify <code>[ci]</code> in the PR title, body, commit-message
or if the PR was tagged with <span class="badge badge-primary">ci</span>. If you leave the box unchecked
tests will be triggered on every pull-request. However you can skip them by using <code>[ci skip]</code>
in the mentioned fields or tag it with <span class="badge badge-primary">ci skip</span>.
</small>
<div class="form-group">
<label for="optinFlagInput">(optional) Custom Flags</label>
<input type="text" class="form-control" id="optinFlagInput" name="optinFlag" aria-describedby="optinFlagHelp" placeholder="default is 'ci'">
<small id="optinFlagHelp" class="form-text text-muted">
If you want to use custom build triggers for opt-in you can specify it here.
</small>
</div>
<div class="form-group">
<input type="text" class="form-control" name="optoutFlag" aria-describedby="optoutFlagHelp" placeholder="default is 'ci skip'">
<small id="optoutFlagHelp" class="form-text text-muted">
If you want to use custom build triggers for opt-out you can specify it here.
</small>
</div>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
Expand Down
84 changes: 75 additions & 9 deletions webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import (
"encoding/json"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/sqlite"
"strings"
"context"
)

func webhook(w http.ResponseWriter, r *http.Request) {
Expand Down Expand Up @@ -54,16 +56,18 @@ func webhook(w http.ResponseWriter, r *http.Request) {
}

// skip all events except for open PRs
if *pr.State != "open" {
if pr.GetState() != "open" {
logger.Println("Ignore closed pull request")
fmt.Fprintf(w, `{}`)
return
}

var repo Repo
err = db.Where("slug = ?", *pr.Base.Repo.FullName).Find(&repo).Error
err = db.Where("slug = ?",
pr.GetBase().GetRepo().GetFullName(),
).Find(&repo).Error
if err != nil {
logger.Println(err, *pr.Base.Repo.FullName)
logger.Println(err, pr.GetBase().GetRepo().GetFullName())
fmt.Fprintf(w, `{"error":"repo not registered"}`)
return
}
Expand All @@ -76,24 +80,86 @@ func webhook(w http.ResponseWriter, r *http.Request) {
// return
//}

var flagExists = false
var buildFlag = repo.OptOutFlag
if repo.OptIn {
buildFlag = repo.OptInFlag
}

// check PR title and body for [ci] or [ci skip] flag
if pr.Title != nil && strings.Contains(pr.GetTitle(),
fmt.Sprintf("[%s]", buildFlag)) {
flagExists = true
} else if pr.Body != nil && strings.Contains(pr.GetBody(),
fmt.Sprintf("[%s]", buildFlag)) {
flagExists = true
} else {
// check labels for build flag if we haven't already found it
for _, label := range pr.Labels {
if label.Name != nil && strings.Contains(label.GetName(), buildFlag) {
flagExists = true
break
}
}

if !flagExists {
// last but not least check the commit message for flags
client := github.NewClient(nil)
commits, _, err := client.PullRequests.ListCommits(
context.Background(),
pr.GetHead().GetUser().GetLogin(),
pr.GetHead().GetRepo().GetName(),
pr.GetNumber(), &github.ListOptions{})

if err == nil && len(commits) > 0 {
// check only last commit since older ones are irrelevant
commitMsg := commits[len(commits)-1].GetCommit().GetMessage()
flagExists = strings.Contains(
commitMsg, fmt.Sprintf("[%s]", buildFlag))
} else {
logger.Printf("Commits is empty or an error occurred: %+v\n", err)
}
}
}

// ignoring pull-request! Repository is set
// to opt-in and no build flag was found
if repo.OptIn && !flagExists {
logger.Printf(
"Ignore optin=%t buildFlag=%s flagExists=%t\n",
repo.OptIn, buildFlag, flagExists)
fmt.Fprintf(w, `{}`)
return
}

// ignoring pull-request! Repository is set
// to opt-out and a skip flag was found
if !repo.OptIn && flagExists {
logger.Printf(
"Ignore optin=%t buildFlag=%s flagExists=%t\n",
repo.OptIn, buildFlag, flagExists)
fmt.Fprintf(w, `{}`)
return
}

build := Build{
RepoID: repo.ID,
Matrix: fmt.Sprintf(
`"PROJECT=%s PRREPO=%s PRSHA=%s"`,
repo.Project,
*pr.Head.Repo.CloneURL,
*pr.Head.SHA,
pr.GetHead().GetRepo().GetCloneURL(),
pr.GetHead().GetSHA(),
),
PRUser: *pr.Head.User.Login,
PRRepo: *pr.Head.Repo.Name,
PRSha: *pr.Head.SHA,
PRUser: pr.GetHead().GetUser().GetLogin(),
PRRepo: pr.GetHead().GetRepo().GetName(),
PRSha: pr.GetHead().GetSHA(),
}

err = db.Create(&build).Error
if err != nil {
logger.Println(err)
fmt.Fprintf(w, `{"error":"database error"}`)
return
}

fmt.Fprintf(w, `{}`)
}

0 comments on commit 9a9c09c

Please sign in to comment.