diff --git a/cmd/droned/assets/css/drone.css b/cmd/droned/assets/css/drone.css index 71fcae13b..7dfec911c 100644 --- a/cmd/droned/assets/css/drone.css +++ b/cmd/droned/assets/css/drone.css @@ -870,6 +870,14 @@ pre { font-size: 22px !IMPORTANT; line-height: 32px !IMPORTANT; } +.alert.alert-build-Success .actions, +.alert.alert-build-Error .actions, +.alert.alert-build-Failure .actions, +.alert.alert-build-Pending .actions, +.alert.alert-build-Started .actions { + float: right; + margin-top: -2px; +} .build-details { background: #FFF; margin-bottom: 40px; diff --git a/cmd/droned/assets/css/drone.less b/cmd/droned/assets/css/drone.less index 7d3fbe684..61f5484e9 100644 --- a/cmd/droned/assets/css/drone.less +++ b/cmd/droned/assets/css/drone.less @@ -184,7 +184,7 @@ body { border:0px; } -// +// // nav-repos // -------------------------------------------- @@ -364,7 +364,7 @@ body { margin-bottom: 10px; } -// +// // build list // -------------------------------------------- @@ -493,7 +493,7 @@ body { .btn.btn-Success { background:rgba(81, 163, 81, 0.75); } -.btn.btn-failure, +.btn.btn-failure, .btn.btn-Failure, .btn.btn-Error { background:rgba(189, 54, 47, 0.8); @@ -911,7 +911,7 @@ textarea { top: 6px; transition: all .15s ease; width: 35px; - z-index: 3; + z-index: 3; border-radius:5px; } @@ -1021,6 +1021,11 @@ pre { line-height: 32px !IMPORTANT; } } + + .actions { + float: right; + margin-top: -2px; + } } .build-details { @@ -1285,5 +1290,3 @@ pre { background: #999; cursor: pointer; } - - diff --git a/cmd/droned/drone.go b/cmd/droned/drone.go index b5641af8c..cea951b6a 100644 --- a/cmd/droned/drone.go +++ b/cmd/droned/drone.go @@ -136,6 +136,7 @@ func setupHandlers() { github = handler.NewGithubHandler(queue) gitlab = handler.NewGitlabHandler(queue) bitbucket = handler.NewBitbucketHandler(queue) + rebuild = handler.NewCommitRebuildHandler(queue) ) m := pat.New() @@ -226,7 +227,9 @@ func setupHandlers() { // handlers for repository, commits and build details m.Get("/:host/:owner/:name/commit/:commit/build/:label/out.txt", handler.RepoHandler(handler.BuildOut)) + m.Post("/:host/:owner/:name/commit/:commit/build/:label/rebuild", handler.RepoAdminHandler(rebuild.CommitRebuild)) m.Get("/:host/:owner/:name/commit/:commit/build/:label", handler.RepoHandler(handler.CommitShow)) + m.Post("/:host/:owner/:name/commit/:commit/rebuild", handler.RepoAdminHandler(rebuild.CommitRebuild)) m.Get("/:host/:owner/:name/commit/:commit", handler.RepoHandler(handler.CommitShow)) m.Get("/:host/:owner/:name/tree", handler.RepoHandler(handler.RepoDashboard)) m.Get("/:host/:owner/:name/status.svg", handler.ErrorHandler(handler.Badge)) diff --git a/pkg/database/builds.go b/pkg/database/builds.go index fefe1e7bb..d3fc4f722 100644 --- a/pkg/database/builds.go +++ b/pkg/database/builds.go @@ -10,7 +10,7 @@ const buildTable = "builds" // SQL Queries to retrieve a list of all Commits belonging to a Repo. const buildStmt = ` -SELECT id, commit_id, slug, status, started, finished, duration, created, updated, stdout +SELECT id, commit_id, slug, status, started, finished, duration, created, updated, stdout, buildscript FROM builds WHERE commit_id = ? ORDER BY slug ASC @@ -18,7 +18,7 @@ ORDER BY slug ASC // SQL Queries to retrieve a Build by id. const buildFindStmt = ` -SELECT id, commit_id, slug, status, started, finished, duration, created, updated, stdout +SELECT id, commit_id, slug, status, started, finished, duration, created, updated, stdout, buildscript FROM builds WHERE id = ? LIMIT 1 @@ -26,7 +26,7 @@ LIMIT 1 // SQL Queries to retrieve a Commit by name and repo id. const buildFindSlugStmt = ` -SELECT id, commit_id, slug, status, started, finished, duration, created, updated, stdout +SELECT id, commit_id, slug, status, started, finished, duration, created, updated, stdout, buildscript FROM builds WHERE slug = ? AND commit_id = ? LIMIT 1 diff --git a/pkg/database/migrate/20140522205400_save_drone_yml.go b/pkg/database/migrate/20140522205400_save_drone_yml.go new file mode 100644 index 000000000..443dc7164 --- /dev/null +++ b/pkg/database/migrate/20140522205400_save_drone_yml.go @@ -0,0 +1,19 @@ +package migrate + +type rev20140522205400 struct{} + +var SaveDroneYml = &rev20140522205400{} + +func (r *rev20140522205400) Revision() int64 { + return 20140522205400 +} + +func (r *rev20140522205400) Up(mg *MigrationDriver) error { + _, err := mg.AddColumn("builds", "buildscript TEXT") + return err +} + +func (r *rev20140522205400) Down(mg *MigrationDriver) error { + _, err := mg.DropColumns("builds", "buildscript") + return err +} diff --git a/pkg/database/migrate/all.go b/pkg/database/migrate/all.go index c745a4edb..14c6a9a74 100644 --- a/pkg/database/migrate/all.go +++ b/pkg/database/migrate/all.go @@ -13,6 +13,7 @@ func (m *Migration) All() *Migration { m.Add(GitHubEnterpriseSupport) m.Add(AddOpenInvitationColumn) m.Add(AddGitlabColumns) + m.Add(SaveDroneYml) // m.Add(...) // ... diff --git a/pkg/database/repos.go b/pkg/database/repos.go index 0d9e2f15e..a344a3d67 100644 --- a/pkg/database/repos.go +++ b/pkg/database/repos.go @@ -90,3 +90,18 @@ func ListReposTeam(id int64) ([]*Repo, error) { err := meddler.QueryAll(db, &repos, repoTeamStmt, id) return repos, err } + +// Checks whether a user is admin of a repo +// Returns true if user owns repo or is on team that owns repo +// Returns true if the user is an admin member of the team. +func IsRepoAdmin(user *User, repo *Repo) (bool, error) { + if user == nil { + return false, nil + } + + if user.ID == repo.UserID { + return true, nil + } + + return IsMemberAdmin(user.ID, repo.TeamID) +} diff --git a/pkg/handler/bitbucket.go b/pkg/handler/bitbucket.go index 48ab7f2cd..be88727bf 100644 --- a/pkg/handler/bitbucket.go +++ b/pkg/handler/bitbucket.go @@ -5,7 +5,6 @@ import ( "net/http" "time" - "github.com/drone/drone/pkg/build/script" "github.com/drone/drone/pkg/database" . "github.com/drone/drone/pkg/model" "github.com/drone/drone/pkg/queue" @@ -83,16 +82,6 @@ func (h *BitbucketHandler) Hook(w http.ResponseWriter, r *http.Request) error { return RenderText(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) } - // parse the build script - buildscript, err := script.ParseBuild([]byte(raw.Data), repo.Params) - if err != nil { - msg := "Could not parse your .drone.yml file. It needs to be a valid drone yaml file.\n\n" + err.Error() + "\n" - if err := saveFailedBuild(commit, msg); err != nil { - return RenderText(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) - } - return RenderText(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) - } - // save the commit to the database if err := database.SaveCommit(commit); err != nil { return RenderText(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) @@ -104,12 +93,13 @@ func (h *BitbucketHandler) Hook(w http.ResponseWriter, r *http.Request) error { build.CommitID = commit.ID build.Created = time.Now().UTC() build.Status = "Pending" + build.BuildScript = raw.Data if err := database.SaveBuild(build); err != nil { return RenderText(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) } // send the build to the queue - h.queue.Add(&queue.BuildTask{Repo: repo, Commit: commit, Build: build, Script: buildscript}) + h.queue.Add(&queue.BuildTask{Repo: repo, Commit: commit, Build: build}) // OK! return RenderText(w, http.StatusText(http.StatusOK), http.StatusOK) diff --git a/pkg/handler/commits.go b/pkg/handler/commits.go index c41620038..442b1f948 100644 --- a/pkg/handler/commits.go +++ b/pkg/handler/commits.go @@ -8,6 +8,7 @@ import ( "github.com/drone/drone/pkg/channel" "github.com/drone/drone/pkg/database" . "github.com/drone/drone/pkg/model" + "github.com/drone/drone/pkg/queue" ) // Display a specific Commit. @@ -33,14 +34,20 @@ func CommitShow(w http.ResponseWriter, r *http.Request, u *User, repo *Repo) err return err } + admin, err := database.IsRepoAdmin(u, repo) + if err != nil { + return err + } + data := struct { - User *User - Repo *Repo - Commit *Commit - Build *Build - Builds []*Build - Token string - }{u, repo, commit, builds[0], builds, ""} + User *User + Repo *Repo + Commit *Commit + Build *Build + Builds []*Build + Token string + IsAdmin bool + }{u, repo, commit, builds[0], builds, "", admin} // get the specific build requested by the user. instead // of a database round trip, we can just loop through the @@ -94,3 +101,70 @@ func saveFailedBuild(commit *Commit, msg string) error { return nil } + +type CommitRebuildHandler struct { + queue *queue.Queue +} + +func NewCommitRebuildHandler(queue *queue.Queue) *CommitRebuildHandler { + return &CommitRebuildHandler{ + queue: queue, + } +} + +// CommitRebuild re-queues a previously built commit. It finds the existing +// commit and build and injects them back into the queue. If the commit +// doesn't exist or has no builds, or if a build label has been passed but +// can't be located, it prints an error. Otherwise, it adds the build/commit +// to the queue and redirects back to the commit page. +func (h *CommitRebuildHandler) CommitRebuild(w http.ResponseWriter, r *http.Request, u *User, repo *Repo) error { + hash := r.FormValue(":commit") + labl := r.FormValue(":label") + host := r.FormValue(":host") + branch := r.FormValue("branch") + if branch == "" { + branch = "master" + } + + // get the commit from the database + commit, err := database.GetCommitBranchHash(branch, hash, repo.ID) + if err != nil { + return err + } + + // get the builds from the database. a commit can have + // multiple sub-builds (or matrix builds) + builds, err := database.ListBuilds(commit.ID) + if err != nil { + return err + } + + build := builds[0] + + if labl != "" { + // get the specific build requested by the user. instead + // of a database round trip, we can just loop through the + // list and extract the requested build. + build = nil + for _, b := range builds { + if b.Slug == labl { + build = b + break + } + } + } + + if build == nil { + return fmt.Errorf("Could not find build: %s", labl) + } + + h.queue.Add(&queue.BuildTask{Repo: repo, Commit: commit, Build: build}) + + if labl != "" { + 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) + } else { + http.Redirect(w, r, fmt.Sprintf("/%s/%s/%s/commit/%s?branch=%s", host, repo.Owner, repo.Name, hash, branch), http.StatusSeeOther) + } + + return nil +} diff --git a/pkg/handler/github.go b/pkg/handler/github.go index 14baf5c5b..0e0237ec1 100644 --- a/pkg/handler/github.go +++ b/pkg/handler/github.go @@ -6,7 +6,6 @@ import ( "strconv" "time" - "github.com/drone/drone/pkg/build/script" "github.com/drone/drone/pkg/database" . "github.com/drone/drone/pkg/model" "github.com/drone/drone/pkg/queue" @@ -131,22 +130,8 @@ func (h *GithubHandler) Hook(w http.ResponseWriter, r *http.Request) error { } // decode the content. Note: Not sure this will ever happen...it basically means a GitHub API issue - raw, err := content.DecodeContent() + buildscript, err := content.DecodeContent() if err != nil { - msg := "Could not decode the yaml from GitHub. Check that your .drone.yml is a valid yaml file.\n" - if err := saveFailedBuild(commit, msg); err != nil { - return RenderText(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) - } - return RenderText(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) - } - - // parse the build script - buildscript, err := script.ParseBuild(raw, repo.Params) - if err != nil { - msg := "Could not parse your .drone.yml file. It needs to be a valid drone yaml file.\n\n" + err.Error() + "\n" - if err := saveFailedBuild(commit, msg); err != nil { - return RenderText(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) - } return RenderText(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) } @@ -161,6 +146,7 @@ func (h *GithubHandler) Hook(w http.ResponseWriter, r *http.Request) error { build.CommitID = commit.ID build.Created = time.Now().UTC() build.Status = "Pending" + build.BuildScript = string(buildscript) if err := database.SaveBuild(build); err != nil { return RenderText(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) } @@ -169,7 +155,7 @@ func (h *GithubHandler) Hook(w http.ResponseWriter, r *http.Request) error { //realtime.CommitPending(repo.UserID, repo.TeamID, repo.ID, commit.ID, repo.Private) //realtime.BuildPending(repo.UserID, repo.TeamID, repo.ID, commit.ID, build.ID, repo.Private) - h.queue.Add(&queue.BuildTask{Repo: repo, Commit: commit, Build: build, Script: buildscript}) //Push(repo, commit, build, buildscript) + h.queue.Add(&queue.BuildTask{Repo: repo, Commit: commit, Build: build}) //Push(repo, commit, build) // OK! return RenderText(w, http.StatusText(http.StatusOK), http.StatusOK) @@ -250,22 +236,12 @@ func (h *GithubHandler) PullRequestHook(w http.ResponseWriter, r *http.Request) } // decode the content - raw, err := content.DecodeContent() + buildscript, err := content.DecodeContent() if err != nil { RenderText(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) return } - // parse the build script - buildscript, err := script.ParseBuild(raw, repo.Params) - if err != nil { - // TODO if the YAML is invalid we should create a commit record - // with an ERROR status so that the user knows why a build wasn't - // triggered in the system - RenderText(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) - return - } - // save the commit to the database if err := database.SaveCommit(commit); err != nil { RenderText(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) @@ -278,6 +254,7 @@ func (h *GithubHandler) PullRequestHook(w http.ResponseWriter, r *http.Request) build.CommitID = commit.ID build.Created = time.Now().UTC() build.Status = "Pending" + build.BuildScript = string(buildscript) if err := database.SaveBuild(build); err != nil { RenderText(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return @@ -285,7 +262,7 @@ func (h *GithubHandler) PullRequestHook(w http.ResponseWriter, r *http.Request) // notify websocket that a new build is pending // TODO we should, for consistency, just put this inside Queue.Add() - h.queue.Add(&queue.BuildTask{Repo: repo, Commit: commit, Build: build, Script: buildscript}) + h.queue.Add(&queue.BuildTask{Repo: repo, Commit: commit, Build: build}) // OK! RenderText(w, http.StatusText(http.StatusOK), http.StatusOK) diff --git a/pkg/handler/gitlab.go b/pkg/handler/gitlab.go index f22c9d880..ae0e63102 100644 --- a/pkg/handler/gitlab.go +++ b/pkg/handler/gitlab.go @@ -9,7 +9,6 @@ import ( "strings" "time" - "github.com/drone/drone/pkg/build/script" "github.com/drone/drone/pkg/database" . "github.com/drone/drone/pkg/model" "github.com/drone/drone/pkg/queue" @@ -207,7 +206,7 @@ func (g *GitlabHandler) Hook(w http.ResponseWriter, r *http.Request) error { // get the drone.yml file from GitHub client := gogitlab.NewGitlab(settings.GitlabApiUrl, g.apiPath, user.GitlabToken) - content, err := client.RepoRawFile(ns(repo.Owner, repo.Name), commit.Hash, ".drone.yml") + buildscript, err := client.RepoRawFile(ns(repo.Owner, repo.Name), commit.Hash, ".drone.yml") if err != nil { msg := "No .drone.yml was found in this repository. You need to add one.\n" if err := saveFailedBuild(commit, msg); err != nil { @@ -216,16 +215,6 @@ func (g *GitlabHandler) Hook(w http.ResponseWriter, r *http.Request) error { return RenderText(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) } - // parse the build script - buildscript, err := script.ParseBuild(content, repo.Params) - if err != nil { - msg := "Could not parse your .drone.yml file. It needs to be a valid drone yaml file.\n\n" + err.Error() + "\n" - if err := saveFailedBuild(commit, msg); err != nil { - return RenderText(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) - } - return RenderText(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) - } - // save the commit to the database if err := database.SaveCommit(commit); err != nil { return RenderText(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) @@ -237,11 +226,12 @@ func (g *GitlabHandler) Hook(w http.ResponseWriter, r *http.Request) error { build.CommitID = commit.ID build.Created = time.Now().UTC() build.Status = "Pending" + build.BuildScript = string(buildscript) if err := database.SaveBuild(build); err != nil { return RenderText(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) } - g.queue.Add(&queue.BuildTask{Repo: repo, Commit: commit, Build: build, Script: buildscript}) + g.queue.Add(&queue.BuildTask{Repo: repo, Commit: commit, Build: build}) // OK! return RenderText(w, http.StatusText(http.StatusOK), http.StatusOK) @@ -287,7 +277,7 @@ func (g *GitlabHandler) PullRequestHook(p *gogitlab.HookPayload, repo *Repo, use commit.Timestamp = src.Commit.AuthoredDateRaw commit.SetAuthor(src.Commit.Author.Email) - content, err := client.RepoRawFile(strconv.Itoa(obj.SourceProjectId), commit.Hash, ".drone.yml") + buildscript, err := client.RepoRawFile(strconv.Itoa(obj.SourceProjectId), commit.Hash, ".drone.yml") if err != nil { msg := "No .drone.yml was found in this repository. You need to add one.\n" if err := saveFailedBuild(commit, msg); err != nil { @@ -296,16 +286,6 @@ func (g *GitlabHandler) PullRequestHook(p *gogitlab.HookPayload, repo *Repo, use return fmt.Errorf("Error to fetch build script: %q", err) } - // parse the build script - buildscript, err := script.ParseBuild(content, repo.Params) - if err != nil { - msg := "Could not parse your .drone.yml file. It needs to be a valid drone yaml file.\n\n" + err.Error() + "\n" - if err := saveFailedBuild(commit, msg); err != nil { - return fmt.Errorf("Failed to save build: %q", err) - } - return fmt.Errorf("Failed to parse build script: %q", err) - } - // save the commit to the database if err := database.SaveCommit(commit); err != nil { return fmt.Errorf("Failed to save commit: %q", err) @@ -317,11 +297,12 @@ func (g *GitlabHandler) PullRequestHook(p *gogitlab.HookPayload, repo *Repo, use build.CommitID = commit.ID build.Created = time.Now().UTC() build.Status = "Pending" + build.BuildScript = string(buildscript) if err := database.SaveBuild(build); err != nil { return fmt.Errorf("Failed to save build: %q", err) } - g.queue.Add(&queue.BuildTask{Repo: repo, Commit: commit, Build: build, Script: buildscript}) + g.queue.Add(&queue.BuildTask{Repo: repo, Commit: commit, Build: build}) return nil } diff --git a/pkg/handler/handler.go b/pkg/handler/handler.go index 2af9150c9..40de6fd3c 100644 --- a/pkg/handler/handler.go +++ b/pkg/handler/handler.go @@ -142,11 +142,9 @@ func (h RepoAdminHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { // The User must own the repository OR be a member // of the Team that owns the repository. - if user.ID != repo.UserID { - if admin, _ := database.IsMemberAdmin(user.ID, repo.TeamID); admin == false { - RenderNotFound(w) - return - } + if admin, _ := database.IsRepoAdmin(user, repo); admin == false { + RenderNotFound(w) + return } if err = h(w, r, user, repo); err != nil { diff --git a/pkg/handler/testing/handler_test.go b/pkg/handler/testing/handler_test.go index 9ea71824d..0616d9616 100644 --- a/pkg/handler/testing/handler_test.go +++ b/pkg/handler/testing/handler_test.go @@ -45,7 +45,7 @@ func TestRepoHandler(t *testing.T) { So(rec.Code, ShouldEqual, 303) }) Convey("Private repo can not be viewed by a non team member", func() { - req, err := http.NewRequest("GET", "/github.com/drone/drone", nil) + req, err := http.NewRequest("GET", "/github.com/drone/drone", nil) So(err, ShouldBeNil) rec := httptest.NewRecorder() setUserSession(rec, req, "rick@el.to.ro") @@ -61,7 +61,7 @@ func dummyUserRepo(w http.ResponseWriter, r *http.Request, u *User, repo *Repo) func setUserSession(w http.ResponseWriter, r *http.Request, username string) { handler.SetCookie(w, r, "_sess", username) - resp := http.Response{Header: w.Header()} + resp := http.Response{Header: w.Header()} for _, v := range resp.Cookies() { r.AddCookie(v) } diff --git a/pkg/model/build.go b/pkg/model/build.go index 44864156e..6dd0e2b6f 100644 --- a/pkg/model/build.go +++ b/pkg/model/build.go @@ -15,16 +15,17 @@ const ( ) type Build struct { - ID int64 `meddler:"id,pk" json:"id"` - CommitID int64 `meddler:"commit_id" json:"-"` - Slug string `meddler:"slug" json:"slug"` - Status string `meddler:"status" json:"status"` - Started time.Time `meddler:"started,utctime" json:"started"` - Finished time.Time `meddler:"finished,utctime" json:"finished"` - Duration int64 `meddler:"duration" json:"duration"` - Created time.Time `meddler:"created,utctime" json:"created"` - Updated time.Time `meddler:"updated,utctime" json:"updated"` - Stdout string `meddler:"stdout" json:"-"` + ID int64 `meddler:"id,pk" json:"id"` + CommitID int64 `meddler:"commit_id" json:"-"` + Slug string `meddler:"slug" json:"slug"` + Status string `meddler:"status" json:"status"` + Started time.Time `meddler:"started,utctime" json:"started"` + Finished time.Time `meddler:"finished,utctime" json:"finished"` + Duration int64 `meddler:"duration" json:"duration"` + Created time.Time `meddler:"created,utctime" json:"created"` + Updated time.Time `meddler:"updated,utctime" json:"updated"` + Stdout string `meddler:"stdout" json:"-"` + BuildScript string `meddler:"buildscript" json:"-"` } // HumanDuration returns a human-readable approximation of a duration diff --git a/pkg/queue/queue.go b/pkg/queue/queue.go index cb7cfba96..587434634 100644 --- a/pkg/queue/queue.go +++ b/pkg/queue/queue.go @@ -1,7 +1,6 @@ package queue import ( - "github.com/drone/drone/pkg/build/script" . "github.com/drone/drone/pkg/model" ) @@ -16,10 +15,6 @@ type BuildTask struct { Repo *Repo Commit *Commit Build *Build - - // Build instructions from the .drone.yml - // file, unmarshalled. - Script *script.Build } // Start N workers with the given build runner. diff --git a/pkg/queue/worker.go b/pkg/queue/worker.go index bf9aeab38..71adb15bd 100644 --- a/pkg/queue/worker.go +++ b/pkg/queue/worker.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/drone/drone/pkg/build/git" r "github.com/drone/drone/pkg/build/repo" + "github.com/drone/drone/pkg/build/script" "github.com/drone/drone/pkg/channel" "github.com/drone/drone/pkg/database" . "github.com/drone/drone/pkg/model" @@ -83,9 +84,16 @@ func (w *worker) execute(task *BuildTask) error { Host: settings.URL().String(), } + // parse the build script + buildscript, err := script.ParseBuild([]byte(task.Build.BuildScript), task.Repo.Params) + if err != nil { + log.Printf("Could not parse your .drone.yml file. It needs to be a valid drone yaml file.\n\n" + err.Error() + "\n") + return err + } + // send all "started" notifications - if task.Script.Notifications != nil { - task.Script.Notifications.Send(context) + if buildscript.Notifications != nil { + buildscript.Notifications.Send(context) } // Send "started" notification to Github @@ -113,7 +121,7 @@ func (w *worker) execute(task *BuildTask) error { // this is not a pull request (for security purposes) if task.Repo.Params != nil && len(task.Commit.PullRequest) == 0 { for k, v := range task.Repo.Params { - task.Script.Env = append(task.Script.Env, k+"="+v) + buildscript.Env = append(buildscript.Env, k+"="+v) } } @@ -126,7 +134,7 @@ func (w *worker) execute(task *BuildTask) error { }() // execute the build - passed, buildErr := w.runBuild(task, buf) + passed, buildErr := w.runBuild(task, buildscript, buf) task.Build.Finished = time.Now().UTC() task.Commit.Finished = time.Now().UTC() @@ -162,14 +170,14 @@ func (w *worker) execute(task *BuildTask) error { channel.Close(consoleslug) // send all "finished" notifications - if task.Script.Notifications != nil { - task.Script.Notifications.Send(context) + if buildscript.Notifications != nil { + buildscript.Notifications.Send(context) } return nil } -func (w *worker) runBuild(task *BuildTask, buf io.Writer) (bool, error) { +func (w *worker) runBuild(task *BuildTask, buildscript *script.Build, buf io.Writer) (bool, error) { repo := &r.Repo{ Name: task.Repo.Slug, Path: task.Repo.URL, @@ -177,11 +185,11 @@ func (w *worker) runBuild(task *BuildTask, buf io.Writer) (bool, error) { Commit: task.Commit.Hash, PR: task.Commit.PullRequest, Dir: filepath.Join("/var/cache/drone/src", task.Repo.Slug), - Depth: git.GitDepth(task.Script.Git), + Depth: git.GitDepth(buildscript.Git), } return w.runner.Run( - task.Script, + buildscript, repo, []byte(task.Repo.PrivateKey), task.Repo.Privileged, diff --git a/pkg/template/pages/repo_commit.html b/pkg/template/pages/repo_commit.html index 2dfd38b34..dfc41ca6d 100644 --- a/pkg/template/pages/repo_commit.html +++ b/pkg/template/pages/repo_commit.html @@ -24,6 +24,18 @@ {{ else }} commit {{ .Commit.HashShort }} to {{.Commit.Branch}} branch {{ end }} + +