// setup a mock docker client for testing purposes. This will use // a test http server that can return mock responses to the docker client. func setup() { mux = http.NewServeMux() server = httptest.NewServer(mux) url, _ := url.Parse(server.URL) url.Scheme = "tcp" os.Setenv("DOCKER_HOST", url.String()) client = docker.New() }
// setup routes for serving dynamic content. func setupHandlers() { queueRunner := queue.NewBuildRunner(docker.New(), timeout) queue := queue.Start(runtime.NumCPU(), queueRunner) hookHandler := handler.NewHookHandler(queue) m := pat.New() m.Get("/login", handler.ErrorHandler(handler.Login)) m.Post("/login", handler.ErrorHandler(handler.Authorize)) m.Get("/logout", handler.ErrorHandler(handler.Logout)) m.Get("/forgot", handler.ErrorHandler(handler.Forgot)) m.Post("/forgot", handler.ErrorHandler(handler.ForgotPost)) m.Get("/reset", handler.ErrorHandler(handler.Reset)) m.Post("/reset", handler.ErrorHandler(handler.ResetPost)) m.Get("/signup", handler.ErrorHandler(handler.SignUp)) m.Post("/signup", handler.ErrorHandler(handler.SignUpPost)) m.Get("/register", handler.ErrorHandler(handler.Register)) m.Post("/register", handler.ErrorHandler(handler.RegisterPost)) m.Get("/accept", handler.UserHandler(handler.TeamMemberAccept)) // handlers for setting up your GitHub repository m.Post("/new/github.com", handler.UserHandler(handler.RepoCreateGithub)) m.Get("/new/github.com", handler.UserHandler(handler.RepoAdd)) // handlers for linking your GitHub account m.Get("/auth/login/github", handler.UserHandler(handler.LinkGithub)) // handlers for dashboard pages m.Get("/dashboard/team/:team", handler.UserHandler(handler.TeamShow)) m.Get("/dashboard", handler.UserHandler(handler.UserShow)) // handlers for user account management m.Get("/account/user/profile", handler.UserHandler(handler.UserEdit)) m.Post("/account/user/profile", handler.UserHandler(handler.UserUpdate)) m.Get("/account/user/delete", handler.UserHandler(handler.UserDeleteConfirm)) m.Post("/account/user/delete", handler.UserHandler(handler.UserDelete)) m.Get("/account/user/password", handler.UserHandler(handler.UserPass)) m.Post("/account/user/password", handler.UserHandler(handler.UserPassUpdate)) m.Get("/account/user/teams/add", handler.UserHandler(handler.TeamAdd)) m.Post("/account/user/teams/add", handler.UserHandler(handler.TeamCreate)) m.Get("/account/user/teams", handler.UserHandler(handler.UserTeams)) // handlers for team managements m.Get("/account/team/:team/profile", handler.UserHandler(handler.TeamEdit)) m.Post("/account/team/:team/profile", handler.UserHandler(handler.TeamUpdate)) m.Get("/account/team/:team/delete", handler.UserHandler(handler.TeamDeleteConfirm)) m.Post("/account/team/:team/delete", handler.UserHandler(handler.TeamDelete)) m.Get("/account/team/:team/members/add", handler.UserHandler(handler.TeamMemberAdd)) m.Post("/account/team/:team/members/add", handler.UserHandler(handler.TeamMemberInvite)) m.Get("/account/team/:team/members/edit", handler.UserHandler(handler.TeamMemberEdit)) m.Post("/account/team/:team/members/edit", handler.UserHandler(handler.TeamMemberUpdate)) m.Post("/account/team/:team/members/delete", handler.UserHandler(handler.TeamMemberDelete)) m.Get("/account/team/:team/members", handler.UserHandler(handler.TeamMembers)) // handlers for system administration m.Get("/account/admin/settings", handler.AdminHandler(handler.AdminSettings)) m.Post("/account/admin/settings", handler.AdminHandler(handler.AdminSettingsUpdate)) m.Get("/account/admin/users/edit", handler.AdminHandler(handler.AdminUserEdit)) m.Post("/account/admin/users/edit", handler.AdminHandler(handler.AdminUserUpdate)) m.Post("/account/admin/users/delete", handler.AdminHandler(handler.AdminUserDelete)) m.Get("/account/admin/users/add", handler.AdminHandler(handler.AdminUserAdd)) m.Post("/account/admin/users", handler.AdminHandler(handler.AdminUserInvite)) m.Get("/account/admin/users", handler.AdminHandler(handler.AdminUserList)) // handlers for GitHub post-commit hooks m.Post("/hook/github.com", handler.ErrorHandler(hookHandler.Hook)) // handlers for first-time installation m.Get("/install", handler.ErrorHandler(handler.Install)) m.Post("/install", handler.ErrorHandler(handler.InstallPost)) // handlers for repository, commits and build details m.Get("/:host/:owner/:name/commit/:commit/build/:label/out.txt", handler.RepoHandler(handler.BuildOut)) m.Get("/:host/:owner/:name/commit/:commit/build/:label", handler.RepoHandler(handler.CommitShow)) 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.png", handler.ErrorHandler(handler.Badge)) m.Get("/:host/:owner/:name/settings", handler.RepoAdminHandler(handler.RepoSettingsForm)) m.Get("/:host/:owner/:name/params", handler.RepoAdminHandler(handler.RepoParamsForm)) m.Get("/:host/:owner/:name/badges", handler.RepoAdminHandler(handler.RepoBadges)) m.Get("/:host/:owner/:name/keys", handler.RepoAdminHandler(handler.RepoKeys)) m.Get("/:host/:owner/:name/delete", handler.RepoAdminHandler(handler.RepoDeleteForm)) m.Post("/:host/:owner/:name/delete", handler.RepoAdminHandler(handler.RepoDelete)) m.Get("/:host/:owner/:name", handler.RepoHandler(handler.RepoDashboard)) m.Post("/:host/:owner/:name", handler.RepoHandler(handler.RepoUpdate)) http.Handle("/feed", websocket.Handler(channel.Read)) // no routes are served at the root URL. Instead we will // redirect the user to his/her dashboard page. m.Get("/", http.RedirectHandler("/dashboard", http.StatusSeeOther)) // the first time a page is requested we should record // the scheme and hostname. http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { // our multiplexer is a bit finnicky and therefore requires // us to strip any trailing slashes in order to correctly // find and match a route. if r.URL.Path != "/" && strings.HasSuffix(r.URL.Path, "/") { http.Redirect(w, r, r.URL.Path[:len(r.URL.Path)-1], http.StatusSeeOther) return } // standard header variables that should be set, for good measure. w.Header().Add("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate") w.Header().Add("X-Frame-Options", "DENY") w.Header().Add("X-Content-Type-Options", "nosniff") w.Header().Add("X-XSS-Protection", "1; mode=block") // ok, now we're ready to serve the request. m.ServeHTTP(w, r) }) }
func run(path string) { dockerClient := docker.New() // parse the Drone yml file s, err := script.ParseBuildFile(path) if err != nil { log.Err(err.Error()) os.Exit(1) return } // get the repository root directory dir := filepath.Dir(path) code := repo.Repo{ Name: dir, Branch: "HEAD", // should we do this? Path: dir, } // does the local repository match the // $GOPATH/src/{package} pattern? This is // important so we know the target location // where the code should be copied inside // the container. if gopath, ok := getRepoPath(dir); ok { code.Dir = gopath } else if gopath, ok := getGoPath(dir); ok { // in this case we found a GOPATH and // reverse engineered the package path code.Dir = gopath } else { // otherwise just use directory name code.Dir = filepath.Base(dir) } // this is where the code gets uploaded to the container // TODO move this code to the build package code.Dir = filepath.Join("/var/cache/drone/src", filepath.Clean(code.Dir)) // track all build results var builders []*build.Builder // ssh key to import into container var key []byte if len(*identity) != 0 { key, err = ioutil.ReadFile(*identity) if err != nil { fmt.Printf("[Error] Could not find or read identity file %s\n", *identity) os.Exit(1) return } } builds := []*script.Build{s} // loop through and create builders for _, b := range builds { //script.Builds { builder := build.New(dockerClient) builder.Build = b builder.Repo = &code builder.Key = key builder.Stdout = os.Stdout builder.Timeout = *timeout if *parallel == true { var buf bytes.Buffer builder.Stdout = &buf } builders = append(builders, builder) } switch *parallel { case false: runSequential(builders) case true: runParallel(builders) } // if in parallel mode, print out the buffer // if we had a failure for _, builder := range builders { if builder.BuildState.ExitCode == 0 { continue } if buf, ok := builder.Stdout.(*bytes.Buffer); ok { log.Noticef("printing stdout for failed build %s", builder.Build.Name) println(buf.String()) } } // this exit code is initially 0 and will // be set to an error code if any of the // builds fail. var exit int fmt.Printf("\nDrone Build Results \033[90m(%v)\033[0m\n", len(builders)) // loop through and print results for _, builder := range builders { build := builder.Build res := builder.BuildState duration := time.Duration(res.Finished - res.Started) switch { case builder.BuildState.ExitCode == 0: fmt.Printf(" \033[32m\u2713\033[0m %v \033[90m(%v)\033[0m\n", build.Name, humanizeDuration(duration*time.Second)) case builder.BuildState.ExitCode != 0: fmt.Printf(" \033[31m\u2717\033[0m %v \033[90m(%v)\033[0m\n", build.Name, humanizeDuration(duration*time.Second)) exit = builder.BuildState.ExitCode } } os.Exit(exit) }
"os/exec" "path/filepath" "strings" "time" "github.com/drone/drone/pkg/build/buildfile" "github.com/drone/drone/pkg/build/docker" "github.com/drone/drone/pkg/build/dockerfile" "github.com/drone/drone/pkg/build/log" "github.com/drone/drone/pkg/build/proxy" "github.com/drone/drone/pkg/build/repo" "github.com/drone/drone/pkg/build/script" ) // instance of the Docker client var client = docker.New() // BuildState stores information about a build // process including the Exit status and various // Runtime statistics (coming soon). type BuildState struct { Started int64 Finished int64 ExitCode int // we may eventually include detailed resource // usage statistics, including including CPU time, // Max RAM, Max Swap, Disk space, and more. } // Builder represents a build process being prepared