github.com/unclejack/drone@v0.2.1-0.20140918182345-831b034aa33b/pkg/handler/bitbucket.go (about)

     1  package handler
     2  
     3  import (
     4  	"database/sql"
     5  	"net/http"
     6  	"time"
     7  
     8  	"github.com/drone/drone/pkg/database"
     9  	. "github.com/drone/drone/pkg/model"
    10  	"github.com/drone/drone/pkg/queue"
    11  	"github.com/drone/go-bitbucket/bitbucket"
    12  )
    13  
    14  type BitbucketHandler struct {
    15  	queue *queue.Queue
    16  }
    17  
    18  func NewBitbucketHandler(queue *queue.Queue) *BitbucketHandler {
    19  	return &BitbucketHandler{
    20  		queue: queue,
    21  	}
    22  }
    23  
    24  // Processes a generic POST-RECEIVE Bitbucket hook and
    25  // attempts to trigger a build.
    26  func (h *BitbucketHandler) Hook(w http.ResponseWriter, r *http.Request) error {
    27  	// get the payload from the request
    28  	payload := r.FormValue("payload")
    29  
    30  	// parse the post-commit hook
    31  	hook, err := bitbucket.ParseHook([]byte(payload))
    32  	if err != nil {
    33  		return err
    34  	}
    35  
    36  	// get the repo from the URL
    37  	repoId := r.FormValue("id")
    38  
    39  	// get the repo from the database, return error if not found
    40  	repo, err := database.GetRepoSlug(repoId)
    41  	if err != nil {
    42  		return RenderText(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
    43  	}
    44  
    45  	// Get the user that owns the repository
    46  	user, err := database.GetUser(repo.UserID)
    47  	if err != nil {
    48  		return RenderText(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
    49  	}
    50  
    51  	// Verify that the commit doesn't already exist.
    52  	// We should never build the same commit twice.
    53  	_, err = database.GetCommitHash(hook.Commits[len(hook.Commits)-1].Hash, repo.ID)
    54  	if err != nil && err != sql.ErrNoRows {
    55  		return RenderText(w, http.StatusText(http.StatusBadGateway), http.StatusBadGateway)
    56  	}
    57  
    58  	commit := &Commit{}
    59  	commit.RepoID = repo.ID
    60  	commit.Branch = hook.Commits[len(hook.Commits)-1].Branch
    61  	commit.Hash = hook.Commits[len(hook.Commits)-1].Hash
    62  	commit.Status = "Pending"
    63  	commit.Created = time.Now().UTC()
    64  	commit.Message = hook.Commits[len(hook.Commits)-1].Message
    65  	commit.Timestamp = time.Now().UTC().String()
    66  	commit.SetAuthor(hook.Commits[len(hook.Commits)-1].Author)
    67  
    68  	// get the github settings from the database
    69  	settings := database.SettingsMust()
    70  
    71  	// create the Bitbucket client
    72  	client := bitbucket.New(
    73  		settings.BitbucketKey,
    74  		settings.BitbucketSecret,
    75  		user.BitbucketToken,
    76  		user.BitbucketSecret,
    77  	)
    78  
    79  	// get the yaml from the database
    80  	raw, err := client.Sources.Find(repo.Owner, repo.Name, commit.Hash, ".drone.yml")
    81  	if err != nil {
    82  		return RenderText(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
    83  	}
    84  
    85  	// save the commit to the database
    86  	if err := database.SaveCommit(commit); err != nil {
    87  		return RenderText(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
    88  	}
    89  
    90  	// save the build to the database
    91  	build := &Build{}
    92  	build.Slug = "1" // TODO
    93  	build.CommitID = commit.ID
    94  	build.Created = time.Now().UTC()
    95  	build.Status = "Pending"
    96  	build.BuildScript = raw.Data
    97  	if err := database.SaveBuild(build); err != nil {
    98  		return RenderText(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
    99  	}
   100  
   101  	// send the build to the queue
   102  	h.queue.Add(&queue.BuildTask{Repo: repo, Commit: commit, Build: build})
   103  
   104  	// OK!
   105  	return RenderText(w, http.StatusText(http.StatusOK), http.StatusOK)
   106  }