func (h RepoAdminHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { user, err := readUser(r) if err != nil { redirectLogin(w, r) return } // repository name from the URL parameters hostParam := r.FormValue(":host") userParam := r.FormValue(":owner") nameParam := r.FormValue(":name") repoName := fmt.Sprintf("%s/%s/%s", hostParam, userParam, nameParam) repo, err := database.GetRepoSlug(repoName) if err != nil { RenderNotFound(w) return } // 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 err = h(w, r, user, repo); err != nil { log.Print(err) RenderError(w, err, http.StatusBadRequest) } }
// helper function that retrieves the repository based // on the URL parameters func readRepo(r *http.Request) (*Repo, error) { // get the repo data from the URL parameters hostParam := r.FormValue(":host") userParam := r.FormValue(":owner") nameParam := r.FormValue(":slug") repoSlug := fmt.Sprintf("%s/%s/%s", hostParam, userParam, nameParam) // get the repo from the database return database.GetRepoSlug(repoSlug) }
// Display a static badge (svg format) for a specific // repository and an optional branch. // TODO this needs to implement basic caching func Badge(w http.ResponseWriter, r *http.Request) error { successParam := r.FormValue("success") failureParam := r.FormValue("failure") branchParam := r.FormValue("branch") hostParam := r.FormValue(":host") ownerParam := r.FormValue(":owner") nameParam := r.FormValue(":name") repoSlug := fmt.Sprintf("%s/%s/%s", hostParam, ownerParam, nameParam) // get the repo from the database repo, err := database.GetRepoSlug(repoSlug) if err != nil { http.NotFound(w, r) return nil } // get the default branch for the repository // if no branch is provided. if len(branchParam) == 0 { branchParam = repo.DefaultBranch() } var badge string // get the latest commit from the database // for the requested branch commit, err := database.GetBranch(repo.ID, branchParam) if err != nil { http.NotFound(w, r) return nil } switch { case commit.Status == "Success" && len(successParam) == 0: // if no success image is provided, we serve a // badge using the shields.io service badge = badgeSuccess case commit.Status == "Success" && len(successParam) != 0: // otherwise we serve the user defined success badge badge = successParam case commit.Status == "Failure" && len(failureParam) == 0: // if no failure image is provided, we serve a // badge using the shields.io service badge = badgeFailure case commit.Status == "Failure" && len(failureParam) != 0: // otherwise we serve the user defined failure badge badge = failureParam default: // otherwise load unknown image badge = badgeUnknown } http.Redirect(w, r, badge, http.StatusSeeOther) return nil }
func (h PublicHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { // repository name from the URL parameters hostParam := r.FormValue(":host") userParam := r.FormValue(":owner") nameParam := r.FormValue(":name") repoName := fmt.Sprintf("%s/%s/%s", hostParam, userParam, nameParam) repo, err := database.GetRepoSlug(repoName) if err != nil || repo == nil { RenderNotFound(w) return } h(w, r, repo) return }
func (h RepoHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { // repository name from the URL parameters hostParam := r.FormValue(":host") userParam := r.FormValue(":owner") nameParam := r.FormValue(":name") repoName := fmt.Sprintf("%s/%s/%s", hostParam, userParam, nameParam) repo, err := database.GetRepoSlug(repoName) if err != nil || repo == nil { RenderNotFound(w) return } // retrieve the user from the database user, err := readUser(r) // if the user is not found, we can still // serve the page assuming the repository // is public. switch { case err != nil && repo.Private == true: redirectLogin(w, r) return case err != nil && repo.Private == false: h(w, r, nil, repo) return } // The User must own the repository OR be a member // of the Team that owns the repository OR the repo // must not be private. if repo.Private && user.ID != repo.UserID { if member, _ := database.IsMember(user.ID, repo.TeamID); !member { RenderNotFound(w) return } } if err = h(w, r, user, repo); err != nil { log.Print(err) RenderError(w, err, http.StatusBadRequest) } }
func setupRepo(urlParts []string, payload *Payload) (*Repo, error) { println("urlParts: ", urlParts) repo, err := database.GetRepoSlug(fmt.Sprintf("%s/%s/%s", urlParts[2], urlParts[3], urlParts[4])) if err != nil { if err != sql.ErrNoRows { return nil, fmt.Errorf("error fetching repo: %s", err) } fmt.Errorf("Repo does not exist in database. %s", err) // urlParts[2] will stay as-is (git.interior.vesseler as it used in url) // need to modify payload.Repo.Url so that git clone works repo_url := payload.Repo.Url if os.Getenv("GOGS_URL") != "" { repo_url = fmt.Sprintf("http://%s/%s/%s", os.Getenv("GOGS_URL"), urlParts[3], urlParts[4]) } repo, err = NewRepo(urlParts[2], urlParts[3], urlParts[4], ScmGit, repo_url) if err != nil { println(err.Error()) return nil, fmt.Errorf("Repo object could not be created %s", err) } fmt.Printf("repo struct created\n") user, err := database.GetUserEmail(payload.Repo.Owner.Email) if err != nil { return repo, fmt.Errorf("Repo could not find user with email %s, err= %s", payload.Repo.Owner.Email, err) } repo.UserID = user.ID repo.Private = payload.Repo.Private err = database.SaveRepo(repo) if err != nil { return repo, fmt.Errorf("Repo could not be saved to database. %s", err) } else { fmt.Printf("repo saved in database\n") return repo, nil } } fmt.Printf("repo exists in database\n") return repo, nil }
// Display a static badge (png format) for a specific // repository and an optional branch. // TODO this needs to implement basic caching func Badge(w http.ResponseWriter, r *http.Request) error { branchParam := r.FormValue("branch") hostParam := r.FormValue(":host") ownerParam := r.FormValue(":owner") nameParam := r.FormValue(":name") repoSlug := fmt.Sprintf("%s/%s/%s", hostParam, ownerParam, nameParam) // get the repo from the database repo, err := database.GetRepoSlug(repoSlug) if err != nil { http.NotFound(w, r) return nil } // get the default branch for the repository // if no branch is provided. if len(branchParam) == 0 { branchParam = repo.DefaultBranch() } // default badge of "unknown" badge := "/img/build_unknown.png" // get the latest commit from the database // for the requested branch commit, err := database.GetBranch(repo.ID, branchParam) if err == nil { switch commit.Status { case "Success": badge = "/img/build_success.png" case "Failing", "Failure": badge = "/img/build_failing.png" } } http.Redirect(w, r, badge, http.StatusSeeOther) return nil }
// Processes a generic POST-RECEIVE hook and // attempts to trigger a build. func Hook(w http.ResponseWriter, r *http.Request) error { // if this is a pull request route // to a different handler if r.Header.Get("X-Github-Event") == "pull_request" { PullRequestHook(w, r) return nil } // get the payload of the message // this should contain a json representation of the // repository and commit details payload := r.FormValue("payload") // parse the github Hook payload hook, err := github.ParseHook([]byte(payload)) if err != nil { println("could not parse hook") return RenderText(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) } // make sure this is being triggered because of a commit // and not something like a tag deletion or whatever if hook.IsTag() || hook.IsGithubPages() || hook.IsHead() == false || hook.IsDeleted() { return RenderText(w, http.StatusText(http.StatusOK), http.StatusOK) } // get the repo from the URL repoId := r.FormValue("id") // get the repo from the database, return error if not found repo, err := database.GetRepoSlug(repoId) if err != nil { return RenderText(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) } // Get the user that owns the repository user, err := database.GetUser(repo.UserID) if err != nil { return RenderText(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) } // Verify that the commit doesn't already exist. // We should never build the same commit twice. _, err = database.GetCommitHash(hook.Head.Id, repo.ID) if err != nil && err != sql.ErrNoRows { println("commit already exists") return RenderText(w, http.StatusText(http.StatusBadGateway), http.StatusBadGateway) } // we really only need: // * repo owner // * repo name // * repo host (github) // * commit hash // * commit timestamp // * commit branch // * commit message // * commit author // * pull request // once we have this data we could just send directly to the queue // and let it handle everything else commit := &Commit{} commit.RepoID = repo.ID commit.Branch = hook.Branch() commit.Hash = hook.Head.Id commit.Status = "Pending" commit.Created = time.Now().UTC() // extract the author and message from the commit // this is kind of experimental, since I don't know // what I'm doing here. if hook.Head != nil && hook.Head.Author != nil { commit.Message = hook.Head.Message commit.Timestamp = hook.Head.Timestamp commit.SetAuthor(hook.Head.Author.Email) } else if hook.Commits != nil && len(hook.Commits) > 0 && hook.Commits[0].Author != nil { commit.Message = hook.Commits[0].Message commit.Timestamp = hook.Commits[0].Timestamp commit.SetAuthor(hook.Commits[0].Author.Email) } // get the drone.yml file from GitHub client := github.New(user.GithubToken) content, err := client.Contents.FindRef(repo.Owner, repo.Name, ".drone.yml", commit.Hash) 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 { return RenderText(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) } return RenderText(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) } // decode the content. Note: Not sure this will ever happen...it basically means a GitHub API issue raw, 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) 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) } // save the build to the database build := &Build{} build.Slug = "1" // TODO build.CommitID = commit.ID build.Created = time.Now().UTC() build.Status = "Pending" if err := database.SaveBuild(build); err != nil { return RenderText(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) } // notify websocket that a new build is pending //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) queue.Add(&queue.BuildTask{Repo: repo, Commit: commit, Build: build, Script: buildscript}) //Push(repo, commit, build, buildscript) // OK! return RenderText(w, http.StatusText(http.StatusOK), http.StatusOK) }
func PullRequestHook(w http.ResponseWriter, r *http.Request) { // get the payload of the message // this should contain a json representation of the // repository and commit details payload := r.FormValue("payload") println("GOT PR HOOK") println(payload) hook, err := github.ParsePullRequestHook([]byte(payload)) if err != nil { RenderText(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) return } // ignore these if hook.Action != "opened" && hook.Action != "synchronize" { RenderText(w, http.StatusText(http.StatusOK), http.StatusOK) return } // get the repo from the URL repoId := r.FormValue("id") // get the repo from the database, return error if not found repo, err := database.GetRepoSlug(repoId) if err != nil { RenderText(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) return } // Get the user that owns the repository user, err := database.GetUser(repo.UserID) if err != nil { RenderText(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) return } // Verify that the commit doesn't already exist. // We should enver build the same commit twice. _, err = database.GetCommitHash(hook.PullRequest.Head.Sha, repo.ID) if err != nil && err != sql.ErrNoRows { RenderText(w, http.StatusText(http.StatusBadGateway), http.StatusBadGateway) return } /////////////////////////////////////////////////////// commit := &Commit{} commit.RepoID = repo.ID commit.Branch = hook.PullRequest.Head.Ref commit.Hash = hook.PullRequest.Head.Sha commit.Status = "Pending" commit.Created = time.Now().UTC() commit.Gravatar = hook.PullRequest.User.GravatarId commit.PullRequest = strconv.Itoa(hook.Number) commit.Message = hook.PullRequest.Title // label := p.PullRequest.Head.Labe // get the drone.yml file from GitHub client := github.New(user.GithubToken) content, err := client.Contents.FindRef(repo.Owner, repo.Name, ".drone.yml", commit.Hash) // TODO should this really be the hash?? if err != nil { println(err.Error()) RenderText(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) return } // decode the content raw, err := content.DecodeContent() if err != nil { RenderText(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) return } // parse the build script buildscript, err := script.ParseBuild(raw) 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) return } // save the build to the database build := &Build{} build.Slug = "1" // TODO build.CommitID = commit.ID build.Created = time.Now().UTC() build.Status = "Pending" if err := database.SaveBuild(build); err != nil { RenderText(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } // notify websocket that a new build is pending // TODO we should, for consistency, just put this inside Queue.Add() queue.Add(&queue.BuildTask{Repo: repo, Commit: commit, Build: build, Script: buildscript}) // OK! RenderText(w, http.StatusText(http.StatusOK), http.StatusOK) }
// Processes a generic POST-RECEIVE Bitbucket hook and // attempts to trigger a build. func (h *BitbucketHandler) Hook(w http.ResponseWriter, r *http.Request) error { // get the payload from the request payload := r.FormValue("payload") // parse the post-commit hook hook, err := bitbucket.ParseHook([]byte(payload)) if err != nil { return err } // get the repo from the URL repoId := r.FormValue("id") // get the repo from the database, return error if not found repo, err := database.GetRepoSlug(repoId) if err != nil { return RenderText(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) } // Get the user that owns the repository user, err := database.GetUser(repo.UserID) if err != nil { return RenderText(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) } // Verify that the commit doesn't already exist. // We should never build the same commit twice. _, err = database.GetCommitHash(hook.Commits[len(hook.Commits)-1].Hash, repo.ID) if err != nil && err != sql.ErrNoRows { return RenderText(w, http.StatusText(http.StatusBadGateway), http.StatusBadGateway) } commit := &Commit{} commit.RepoID = repo.ID commit.Branch = hook.Commits[len(hook.Commits)-1].Branch commit.Hash = hook.Commits[len(hook.Commits)-1].Hash commit.Status = "Pending" commit.Created = time.Now().UTC() commit.Message = hook.Commits[len(hook.Commits)-1].Message commit.Timestamp = time.Now().UTC().String() commit.SetAuthor(hook.Commits[len(hook.Commits)-1].Author) // get the github settings from the database settings := database.SettingsMust() // create the Bitbucket client client := bitbucket.New( settings.BitbucketKey, settings.BitbucketSecret, user.BitbucketToken, user.BitbucketSecret, ) // get the yaml from the database raw, err := client.Sources.Find(repo.Owner, repo.Name, commit.Hash, ".drone.yml") if err != nil { 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) } // save the build to the database build := &Build{} build.Slug = "1" // TODO build.CommitID = commit.ID build.Created = time.Now().UTC() build.Status = "Pending" 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}) // OK! return RenderText(w, http.StatusText(http.StatusOK), http.StatusOK) }
func (g *GitlabHandler) Hook(w http.ResponseWriter, r *http.Request) error { rID := r.FormValue("id") repo, err := database.GetRepoSlug(rID) if err != nil { return RenderText(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) } user, err := database.GetUser(repo.UserID) if err != nil { return RenderText(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) } payload, _ := ioutil.ReadAll(r.Body) parsed, err := gogitlab.ParseHook(payload) if err != nil { return err } if parsed.ObjectKind == "merge_request" { fmt.Println(string(payload)) if err := g.PullRequestHook(parsed, repo, user); err != nil { return err } return RenderText(w, http.StatusText(http.StatusOK), http.StatusOK) } if len(parsed.After) == 0 { return RenderText(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) } _, err = database.GetCommitHash(parsed.After, repo.ID) if err != nil && err != sql.ErrNoRows { fmt.Println("commit already exists") return RenderText(w, http.StatusText(http.StatusBadGateway), http.StatusBadGateway) } commit := &Commit{} commit.RepoID = repo.ID commit.Branch = parsed.Branch() commit.Hash = parsed.After commit.Status = "Pending" commit.Created = time.Now().UTC() head := parsed.Head() commit.Message = head.Message commit.Timestamp = head.Timestamp if head.Author != nil { commit.SetAuthor(head.Author.Email) } else { commit.SetAuthor(parsed.UserName) } // get the github settings from the database settings := database.SettingsMust() // get the drone.yml file from GitHub client := gogitlab.NewGitlab(settings.GitlabApiUrl, g.apiPath, user.GitlabToken) 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 { 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) } // save the build to the database build := &Build{} build.Slug = "1" // TODO 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}) // OK! return RenderText(w, http.StatusText(http.StatusOK), http.StatusOK) }
// TestGetRepoSlug tests the ability to retrieve a Repo // from the database by it's Canonical Name. func TestGetRepoSlug(t *testing.T) { Setup() defer Teardown() repo, err := database.GetRepoSlug("github.com/drone/drone") if err != nil { t.Error(err) } if repo.ID != 1 { t.Errorf("Exepected ID %d, got %d", 1, repo.ID) } if repo.Slug != "github.com/drone/drone" { t.Errorf("Exepected Slug %s, got %s", "github.com/drone/drone", repo.Slug) } if repo.Host != "github.com" { t.Errorf("Exepected Host %s, got %s", "github.com", repo.Host) } if repo.Owner != "drone" { t.Errorf("Exepected Owner %s, got %s", "drone", repo.Owner) } if repo.Name != "drone" { t.Errorf("Exepected Name %s, got %s", "drone", repo.Name) } if repo.Private != true { t.Errorf("Exepected Private %v, got %v", true, repo.Private) } if repo.Disabled != false { t.Errorf("Exepected Private %v, got %v", false, repo.Disabled) } if repo.SCM != "git" { t.Errorf("Exepected Type %s, got %s", "git", repo.SCM) } if repo.URL != "[email protected]:drone/drone.git" { t.Errorf("Exepected URL %s, got %s", "[email protected]:drone/drone.git", repo.URL) } if repo.Username != "no username" { t.Errorf("Exepected Username %s, got %s", "no username", repo.Username) } if repo.Password != "no password" { t.Errorf("Exepected Password %s, got %s", "no password", repo.Password) } if repo.PublicKey != pubkey { t.Errorf("Exepected PublicKey %s, got %s", "public key", repo.PublicKey) } if repo.PrivateKey != privkey { t.Errorf("Exepected PrivateKey %s, got %s", "private key", repo.PrivateKey) } if repo.UserID != 1 { t.Errorf("Exepected ID %d, got %d", 1, repo.UserID) } if repo.TeamID != 1 { t.Errorf("Exepected ID %d, got %d", 1, repo.TeamID) } }
// Tests the ability to create GitHub repositories. func Test_GitHubCreate(t *testing.T) { // seed the database with values SetupFixtures() defer TeardownFixtures() // mock request req := http.Request{} req.Form = url.Values{} // get user that will add repositories user, _ := database.GetUser(1) settings := database.SettingsMust() Convey("Given request to setup github repo", t, func() { Convey("When repository is public", func() { req.Form.Set("owner", "example") req.Form.Set("name", "public") req.Form.Set("team", "") res := httptest.NewRecorder() err := handler.RepoCreateGithub(res, &req, user) repo, _ := database.GetRepoSlug(settings.GitHubDomain + "/example/public") Convey("The repository is created", func() { So(err, ShouldBeNil) So(repo, ShouldNotBeNil) So(repo.ID, ShouldNotEqual, 0) So(repo.Owner, ShouldEqual, "example") So(repo.Name, ShouldEqual, "public") So(repo.Host, ShouldEqual, settings.GitHubDomain) So(repo.TeamID, ShouldEqual, 0) So(repo.UserID, ShouldEqual, user.ID) So(repo.Private, ShouldEqual, false) So(repo.SCM, ShouldEqual, "git") }) Convey("The repository is public", func() { So(repo.Private, ShouldEqual, false) }) }) Convey("When repository is private", func() { req.Form.Set("owner", "example") req.Form.Set("name", "private") req.Form.Set("team", "") res := httptest.NewRecorder() err := handler.RepoCreateGithub(res, &req, user) repo, _ := database.GetRepoSlug(settings.GitHubDomain + "/example/private") Convey("The repository is created", func() { So(err, ShouldBeNil) So(repo, ShouldNotBeNil) So(repo.ID, ShouldNotEqual, 0) }) Convey("The repository is private", func() { So(repo.Private, ShouldEqual, true) }) }) Convey("When repository is not found", func() { req.Form.Set("owner", "example") req.Form.Set("name", "notfound") req.Form.Set("team", "") res := httptest.NewRecorder() err := handler.RepoCreateGithub(res, &req, user) Convey("The result is an error", func() { So(err, ShouldNotBeNil) So(err.Error(), ShouldEqual, "Unable to find GitHub repository example/notfound.") }) Convey("The repository is not created", func() { _, err := database.GetRepoSlug("example/notfound") So(err, ShouldNotBeNil) So(err, ShouldEqual, sql.ErrNoRows) }) }) Convey("When repository hook is not writable", func() { req.Form.Set("owner", "example") req.Form.Set("name", "hookerr") req.Form.Set("team", "") res := httptest.NewRecorder() err := handler.RepoCreateGithub(res, &req, user) Convey("The result is an error", func() { So(err, ShouldNotBeNil) So(err.Error(), ShouldEqual, "Unable to add Hook to your GitHub repository.") }) Convey("The repository is not created", func() { _, err := database.GetRepoSlug("example/hookerr") So(err, ShouldNotBeNil) So(err, ShouldEqual, sql.ErrNoRows) }) }) Convey("When repository ssh key is not writable", func() { req.Form.Set("owner", "example") req.Form.Set("name", "keyerr") req.Form.Set("team", "") res := httptest.NewRecorder() err := handler.RepoCreateGithub(res, &req, user) Convey("The result is an error", func() { So(err, ShouldNotBeNil) So(err.Error(), ShouldEqual, "Unable to add Public Key to your GitHub repository.") }) Convey("The repository is not created", func() { _, err := database.GetRepoSlug("example/keyerr") So(err, ShouldNotBeNil) So(err, ShouldEqual, sql.ErrNoRows) }) }) Convey("When a team is provided", func() { req.Form.Set("owner", "example") req.Form.Set("name", "team") req.Form.Set("team", "drone") res := httptest.NewRecorder() // invoke handler err := handler.RepoCreateGithub(res, &req, user) team, _ := database.GetTeamSlug("drone") repo, _ := database.GetRepoSlug(settings.GitHubDomain + "/example/team") Convey("The repository is created", func() { So(err, ShouldBeNil) So(repo, ShouldNotBeNil) So(repo.ID, ShouldNotEqual, 0) }) Convey("The team should be set", func() { So(repo.TeamID, ShouldEqual, team.ID) }) }) Convey("When a team is not found", func() { req.Form.Set("owner", "example") req.Form.Set("name", "public") req.Form.Set("team", "faketeam") res := httptest.NewRecorder() err := handler.RepoCreateGithub(res, &req, user) Convey("The result is an error", func() { So(err, ShouldNotBeNil) So(err.Error(), ShouldEqual, "Unable to find Team faketeam.") }) }) Convey("When a team is forbidden", func() { req.Form.Set("owner", "example") req.Form.Set("name", "public") req.Form.Set("team", "golang") res := httptest.NewRecorder() err := handler.RepoCreateGithub(res, &req, user) Convey("The result is an error", func() { So(err, ShouldNotBeNil) So(err.Error(), ShouldEqual, "Invalid permission to access Team golang.") }) }) }) }