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

     1  package handler
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  	"time"
     7  
     8  	"github.com/drone/drone/pkg/channel"
     9  	"github.com/drone/drone/pkg/database"
    10  	. "github.com/drone/drone/pkg/model"
    11  	"github.com/drone/drone/pkg/queue"
    12  )
    13  
    14  // Display a specific Commit.
    15  func CommitShow(w http.ResponseWriter, r *http.Request, u *User, repo *Repo) error {
    16  	branch := r.FormValue("branch")
    17  	if branch == "" {
    18  		branch = "master"
    19  	}
    20  
    21  	hash := r.FormValue(":commit")
    22  	labl := r.FormValue(":label")
    23  
    24  	// get the commit from the database
    25  	commit, err := database.GetCommitBranchHash(branch, hash, repo.ID)
    26  	if err != nil {
    27  		return err
    28  	}
    29  
    30  	// get the builds from the database. a commit can have
    31  	// multiple sub-builds (or matrix builds)
    32  	builds, err := database.ListBuilds(commit.ID)
    33  	if err != nil {
    34  		return err
    35  	}
    36  
    37  	admin, err := database.IsRepoAdmin(u, repo)
    38  	if err != nil {
    39  		return err
    40  	}
    41  
    42  	data := struct {
    43  		User    *User
    44  		Repo    *Repo
    45  		Commit  *Commit
    46  		Build   *Build
    47  		Builds  []*Build
    48  		Token   string
    49  		IsAdmin bool
    50  	}{u, repo, commit, builds[0], builds, "", admin}
    51  
    52  	// get the specific build requested by the user. instead
    53  	// of a database round trip, we can just loop through the
    54  	// list and extract the requested build.
    55  	for _, b := range builds {
    56  		if b.Slug == labl {
    57  			data.Build = b
    58  			break
    59  		}
    60  	}
    61  
    62  	// generate a token to connect with the websocket
    63  	// handler and stream output, if the build is running.
    64  	data.Token = channel.Token(fmt.Sprintf(
    65  		"%s/%s/%s/commit/%s/%s/builds/%s", repo.Host, repo.Owner, repo.Name, commit.Branch, commit.Hash, builds[0].Slug))
    66  
    67  	// render the repository template.
    68  	return RenderTemplate(w, "repo_commit.html", &data)
    69  }
    70  
    71  // Helper method for saving a failed build or commit in the case where it never starts to build.
    72  // This can happen if the yaml is bad or doesn't exist.
    73  func saveFailedBuild(commit *Commit, msg string) error {
    74  
    75  	// Set the commit to failed
    76  	commit.Status = "Failure"
    77  	commit.Created = time.Now().UTC()
    78  	commit.Finished = commit.Created
    79  	commit.Duration = 0
    80  	if err := database.SaveCommit(commit); err != nil {
    81  		return err
    82  	}
    83  
    84  	// save the build to the database
    85  	build := &Build{}
    86  	build.Slug = "1" // TODO: This should not be hardcoded
    87  	build.CommitID = commit.ID
    88  	build.Created = time.Now().UTC()
    89  	build.Finished = build.Created
    90  	commit.Duration = 0
    91  	build.Status = "Failure"
    92  	build.Stdout = msg
    93  	if err := database.SaveBuild(build); err != nil {
    94  		return err
    95  	}
    96  
    97  	// TODO: Should the status be Error instead of Failure?
    98  
    99  	// TODO: Do we need to update the branch table too?
   100  
   101  	return nil
   102  
   103  }
   104  
   105  type CommitRebuildHandler struct {
   106  	queue *queue.Queue
   107  }
   108  
   109  func NewCommitRebuildHandler(queue *queue.Queue) *CommitRebuildHandler {
   110  	return &CommitRebuildHandler{
   111  		queue: queue,
   112  	}
   113  }
   114  
   115  // CommitRebuild re-queues a previously built commit. It finds the existing
   116  // commit and build and injects them back into the queue.  If the commit
   117  // doesn't exist or has no builds, or if a build label has been passed but
   118  // can't be located, it prints an error. Otherwise, it adds the build/commit
   119  // to the queue and redirects back to the commit page.
   120  func (h *CommitRebuildHandler) CommitRebuild(w http.ResponseWriter, r *http.Request, u *User, repo *Repo) error {
   121  	hash := r.FormValue(":commit")
   122  	labl := r.FormValue(":label")
   123  	host := r.FormValue(":host")
   124  	branch := r.FormValue("branch")
   125  	if branch == "" {
   126  		branch = "master"
   127  	}
   128  
   129  	// get the commit from the database
   130  	commit, err := database.GetCommitBranchHash(branch, hash, repo.ID)
   131  	if err != nil {
   132  		return err
   133  	}
   134  
   135  	// get the builds from the database. a commit can have
   136  	// multiple sub-builds (or matrix builds)
   137  	builds, err := database.ListBuilds(commit.ID)
   138  	if err != nil {
   139  		return err
   140  	}
   141  
   142  	build := builds[0]
   143  
   144  	if labl != "" {
   145  		// get the specific build requested by the user. instead
   146  		// of a database round trip, we can just loop through the
   147  		// list and extract the requested build.
   148  		build = nil
   149  		for _, b := range builds {
   150  			if b.Slug == labl {
   151  				build = b
   152  				break
   153  			}
   154  		}
   155  	}
   156  
   157  	if build == nil {
   158  		return fmt.Errorf("Could not find build: %s", labl)
   159  	}
   160  
   161  	h.queue.Add(&queue.BuildTask{Repo: repo, Commit: commit, Build: build})
   162  
   163  	if labl != "" {
   164  		http.Redirect(w, r, fmt.Sprintf("/%s/%s/%s/commit/%s/build/%s?branch=%s", host, repo.Owner, repo.Name, hash, labl, branch), http.StatusSeeOther)
   165  	} else {
   166  		http.Redirect(w, r, fmt.Sprintf("/%s/%s/%s/commit/%s?branch=%s", host, repo.Owner, repo.Name, hash, branch), http.StatusSeeOther)
   167  	}
   168  
   169  	return nil
   170  }