Merge branch 'example-fixture'
This commit is contained in:
commit
854d3443d7
8 changed files with 897 additions and 11 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -14,3 +14,4 @@ deb/drone/usr/local/bin/drone
|
|||
deb/drone/usr/local/bin/droned
|
||||
|
||||
.vagrant
|
||||
*.out
|
|
@ -474,7 +474,7 @@ func (b *Builder) writeBuildScript(dir string) error {
|
|||
f.WriteEnv("DRONE_PR", b.Repo.PR)
|
||||
f.WriteEnv("DRONE_BUILD_DIR", b.Repo.Dir)
|
||||
|
||||
// add /etc/hosts entries
|
||||
// add /etc/hosts entries
|
||||
for _, mapping := range b.Build.Hosts {
|
||||
f.WriteHost(mapping)
|
||||
}
|
||||
|
|
380
pkg/build/build_test.go
Normal file
380
pkg/build/build_test.go
Normal file
|
@ -0,0 +1,380 @@
|
|||
package build
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/drone/drone/pkg/build/buildfile"
|
||||
"github.com/drone/drone/pkg/build/docker"
|
||||
"github.com/drone/drone/pkg/build/proxy"
|
||||
"github.com/drone/drone/pkg/build/repo"
|
||||
"github.com/drone/drone/pkg/build/script"
|
||||
)
|
||||
|
||||
var (
|
||||
// mux is the HTTP request multiplexer used with the test server.
|
||||
mux *http.ServeMux
|
||||
|
||||
// server is a test HTTP server used to provide mock API responses.
|
||||
server *httptest.Server
|
||||
|
||||
// docker client
|
||||
client *docker.Client
|
||||
)
|
||||
|
||||
// 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()
|
||||
}
|
||||
|
||||
func teardown() {
|
||||
server.Close()
|
||||
}
|
||||
|
||||
// TestSetup will test our ability to successfully create a Docker
|
||||
// image for the build.
|
||||
func TestSetup(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
// Handles a request to inspect the Go 1.2 image
|
||||
// This will return a dummy image ID, so that the system knows
|
||||
// the build image exists, and doens't need to be downloaded.
|
||||
mux.HandleFunc("/v1.9/images/bradrydzewski/go:1.2/json", func(w http.ResponseWriter, r *http.Request) {
|
||||
body := `[{ "id": "7bf9ce0ffb7236ca68da0f9fed0e1682053b393db3c724ff3c5a4e8c0793b34c" }]`
|
||||
w.Write([]byte(body))
|
||||
})
|
||||
|
||||
// Handles a request to create the build image, with the build
|
||||
// script injected. This will return a dummy stream.
|
||||
mux.HandleFunc("/v1.9/build", func(w http.ResponseWriter, r *http.Request) {
|
||||
body := `{"stream":"Step 1..."}`
|
||||
w.Write([]byte(body))
|
||||
})
|
||||
|
||||
// Handles a request to inspect the newly created build image. Note
|
||||
// that we are doing a "wildcard" url match here, since the name of
|
||||
// the image will be random. This will return a dummy image ID
|
||||
// to confirm the build image was created successfully.
|
||||
mux.HandleFunc("/v1.9/images/", func(w http.ResponseWriter, r *http.Request) {
|
||||
body := `{ "id": "7bf9ce0ffb7236ca68da0f9fed0e1682053b393db3c724ff3c5a4e8c0793b34c" }`
|
||||
w.Write([]byte(body))
|
||||
})
|
||||
|
||||
b := Builder{}
|
||||
b.Repo = &repo.Repo{}
|
||||
b.Repo.Path = "git://github.com/drone/drone.git"
|
||||
b.Build = &script.Build{}
|
||||
b.Build.Image = "go1.2"
|
||||
b.dockerClient = client
|
||||
|
||||
if err := b.setup(); err != nil {
|
||||
t.Errorf("Expected success, got %s", err)
|
||||
}
|
||||
|
||||
// verify the Image is being correctly set
|
||||
if b.image == nil {
|
||||
t.Errorf("Expected image not nil")
|
||||
}
|
||||
|
||||
expectedID := "7bf9ce0ffb7236ca68da0f9fed0e1682053b393db3c724ff3c5a4e8c0793b34c"
|
||||
if b.image.ID != expectedID {
|
||||
t.Errorf("Expected image.ID %s, got %s", expectedID, b.image.ID)
|
||||
}
|
||||
}
|
||||
|
||||
// TestSetupEmptyImage will test our ability to handle a nil or
|
||||
// blank Docker build image. We expect this to return an error.
|
||||
func TestSetupEmptyImage(t *testing.T) {
|
||||
b := Builder{Build: &script.Build{}}
|
||||
var got, want = b.setup(), "Error: missing Docker image"
|
||||
|
||||
if got == nil || got.Error() != want {
|
||||
t.Errorf("Expected error %s, got %s", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
// TestSetupUnknownService will test our ability to handle an
|
||||
// unknown or unsupported service (i.e. mysql).
|
||||
func TestSetupUnknownService(t *testing.T) {
|
||||
b := Builder{}
|
||||
b.Repo = &repo.Repo{}
|
||||
b.Repo.Path = "git://github.com/drone/drone.git"
|
||||
b.Build = &script.Build{}
|
||||
b.Build.Image = "go1.2"
|
||||
b.Build.Services = append(b.Build.Services, "not-found")
|
||||
|
||||
var got, want = b.setup(), "Error: Invalid or unknown service not-found"
|
||||
if got == nil || got.Error() != want {
|
||||
t.Errorf("Expected error %s, got %s", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
// TestSetupErrorRunDaemonPorts will test our ability to handle a
|
||||
// failure when starting a service (i.e. mysql) as a daemon.
|
||||
func TestSetupErrorRunDaemonPorts(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/v1.9/containers/create", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
})
|
||||
|
||||
b := Builder{}
|
||||
b.Repo = &repo.Repo{}
|
||||
b.Repo.Path = "git://github.com/drone/drone.git"
|
||||
b.Build = &script.Build{}
|
||||
b.Build.Image = "go1.2"
|
||||
b.Build.Services = append(b.Build.Services, "mysql")
|
||||
b.dockerClient = client
|
||||
|
||||
var got, want = b.setup(), docker.ErrBadRequest
|
||||
if got == nil || got != want {
|
||||
t.Errorf("Expected error %s, got %s", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
// TestSetupErrorServiceInspect will test our ability to handle a
|
||||
// failure when a service (i.e. mysql) is started successfully,
|
||||
// but cannot be queried post-start with the Docker remote API.
|
||||
func TestSetupErrorServiceInspect(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/v1.9/containers/create", func(w http.ResponseWriter, r *http.Request) {
|
||||
body := `{ "Id":"e90e34656806", "Warnings":[] }`
|
||||
w.Write([]byte(body))
|
||||
})
|
||||
|
||||
mux.HandleFunc("/v1.9/containers/e90e34656806/start", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
})
|
||||
|
||||
mux.HandleFunc("/v1.9/containers/e90e34656806/json", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
})
|
||||
|
||||
b := Builder{}
|
||||
b.Repo = &repo.Repo{}
|
||||
b.Repo.Path = "git://github.com/drone/drone.git"
|
||||
b.Build = &script.Build{}
|
||||
b.Build.Image = "go1.2"
|
||||
b.Build.Services = append(b.Build.Services, "mysql")
|
||||
b.dockerClient = client
|
||||
|
||||
var got, want = b.setup(), docker.ErrBadRequest
|
||||
if got == nil || got != want {
|
||||
t.Errorf("Expected error %s, got %s", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
// TestSetupErrorImagePull will test our ability to handle a
|
||||
// failure when a the build image cannot be pulled from the index.
|
||||
func TestSetupErrorImagePull(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/v1.9/images/bradrydzewski/go:1.2/json", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
})
|
||||
|
||||
mux.HandleFunc("/v1.9/images/create", func(w http.ResponseWriter, r *http.Request) {
|
||||
// validate ?fromImage=bradrydzewski/go&tag=1.2
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
})
|
||||
|
||||
b := Builder{}
|
||||
b.Repo = &repo.Repo{}
|
||||
b.Repo.Path = "git://github.com/drone/drone.git"
|
||||
b.Build = &script.Build{}
|
||||
b.Build.Image = "go1.2"
|
||||
b.dockerClient = client
|
||||
|
||||
var got, want = b.setup(), docker.ErrBadRequest
|
||||
if got == nil || got != want {
|
||||
t.Errorf("Expected error %s, got %s", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
// TestSetupErrorBuild will test our ability to handle a failure
|
||||
// when creating a Docker image with the injected build script,
|
||||
// ssh keys, etc.
|
||||
func TestSetupErrorBuild(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/v1.9/images/bradrydzewski/go:1.2/json", func(w http.ResponseWriter, r *http.Request) {
|
||||
body := `[{ "id": "7bf9ce0ffb7236ca68da0f9fed0e1682053b393db3c724ff3c5a4e8c0793b34c" }]`
|
||||
w.Write([]byte(body))
|
||||
})
|
||||
|
||||
mux.HandleFunc("/v1.9/build", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
})
|
||||
|
||||
b := Builder{}
|
||||
b.Repo = &repo.Repo{}
|
||||
b.Repo.Path = "git://github.com/drone/drone.git"
|
||||
b.Build = &script.Build{}
|
||||
b.Build.Image = "go1.2"
|
||||
b.dockerClient = client
|
||||
|
||||
var got, want = b.setup(), docker.ErrBadRequest
|
||||
if got == nil || got != want {
|
||||
t.Errorf("Expected error %s, got %s", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
// TestSetupErrorBuildInspect will test our ability to handle a failure
|
||||
// when we successfully create a Docker image with the injected build script,
|
||||
// ssh keys, etc, however, we cannot inspect it post-creation using
|
||||
// the Docker remote API.
|
||||
func TestSetupErrorBuildInspect(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc("/v1.9/images/bradrydzewski/go:1.2/json", func(w http.ResponseWriter, r *http.Request) {
|
||||
body := `[{ "id": "7bf9ce0ffb7236ca68da0f9fed0e1682053b393db3c724ff3c5a4e8c0793b34c" }]`
|
||||
w.Write([]byte(body))
|
||||
})
|
||||
|
||||
mux.HandleFunc("/v1.9/build", func(w http.ResponseWriter, r *http.Request) {
|
||||
body := `{"stream":"Step 1..."}`
|
||||
w.Write([]byte(body))
|
||||
})
|
||||
|
||||
mux.HandleFunc("/v1.9/images/", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
})
|
||||
|
||||
b := Builder{}
|
||||
b.Repo = &repo.Repo{}
|
||||
b.Repo.Path = "git://github.com/drone/drone.git"
|
||||
b.Build = &script.Build{}
|
||||
b.Build.Image = "go1.2"
|
||||
b.dockerClient = client
|
||||
|
||||
var got, want = b.setup(), docker.ErrBadRequest
|
||||
if got == nil || got != want {
|
||||
t.Errorf("Expected error %s, got %s", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
// TestTeardown will test our ability to sucessfully teardown a
|
||||
// Docker-based build environment.
|
||||
func TestTeardown(t *testing.T) {}
|
||||
|
||||
// TestTeardownContainerFail will test our ability to handle a
|
||||
// failure to stop and remove the build container.
|
||||
func TestTeardownContainerFail(t *testing.T) {}
|
||||
|
||||
// TestTeardownImageFail will test our ability to handle a
|
||||
// failure to stop and remove the build image.
|
||||
func TestTeardownImageFail(t *testing.T) {}
|
||||
|
||||
func TestWriteIdentifyFile(t *testing.T) {
|
||||
// temporary directory to store file
|
||||
dir, _ := ioutil.TempDir("", "drone-test-")
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
b := Builder{}
|
||||
b.Key = []byte("ssh-rsa AAA...")
|
||||
b.writeIdentifyFile(dir)
|
||||
|
||||
// persist a dummy id_rsa keyfile to disk
|
||||
keyfile, err := ioutil.ReadFile(filepath.Join(dir, "id_rsa"))
|
||||
if err != nil {
|
||||
t.Errorf("Expected id_rsa file saved to disk")
|
||||
}
|
||||
|
||||
if string(keyfile) != string(b.Key) {
|
||||
t.Errorf("Expected id_rsa value saved as %s, got %s", b.Key, keyfile)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriteProxyScript(t *testing.T) {
|
||||
// temporary directory to store file
|
||||
dir, _ := ioutil.TempDir("", "drone-test-")
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
// fake service container that we'll assume was part of the yaml
|
||||
// and should be attached to the build container.
|
||||
c := docker.Container{
|
||||
NetworkSettings: &docker.NetworkSettings{
|
||||
IPAddress: "172.1.4.5",
|
||||
Ports: map[docker.Port][]docker.PortBinding{
|
||||
docker.NewPort("tcp", "3306"): nil,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// this should generate the following proxy file
|
||||
p := proxy.Proxy{}
|
||||
p.Set("3306", "172.1.4.5")
|
||||
want := p.String()
|
||||
|
||||
b := Builder{}
|
||||
b.services = append(b.services, &c)
|
||||
b.writeProxyScript(dir)
|
||||
|
||||
// persist a dummy proxy script to disk
|
||||
got, err := ioutil.ReadFile(filepath.Join(dir, "proxy.sh"))
|
||||
if err != nil {
|
||||
t.Errorf("Expected proxy.sh file saved to disk")
|
||||
}
|
||||
|
||||
if string(got) != want {
|
||||
t.Errorf("Expected proxy.sh value saved as %s, got %s", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriteBuildScript(t *testing.T) {
|
||||
// temporary directory to store file
|
||||
dir, _ := ioutil.TempDir("", "drone-test-")
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
b := Builder{}
|
||||
b.Build = &script.Build{
|
||||
Hosts: []string{"127.0.0.1"}}
|
||||
b.Repo = &repo.Repo{
|
||||
Path: "git://github.com/drone/drone.git",
|
||||
Branch: "master",
|
||||
Commit: "e7e046b35",
|
||||
PR: "123",
|
||||
Dir: "/var/cache/drone/github.com/drone/drone"}
|
||||
b.writeBuildScript(dir)
|
||||
|
||||
// persist a dummy build script to disk
|
||||
script, err := ioutil.ReadFile(filepath.Join(dir, "drone"))
|
||||
if err != nil {
|
||||
t.Errorf("Expected id_rsa file saved to disk")
|
||||
}
|
||||
|
||||
f := buildfile.New()
|
||||
f.WriteEnv("CI", "true")
|
||||
f.WriteEnv("DRONE", "true")
|
||||
f.WriteEnv("DRONE_BRANCH", "master")
|
||||
f.WriteEnv("DRONE_COMMIT", "e7e046b35")
|
||||
f.WriteEnv("DRONE_PR", "123")
|
||||
f.WriteEnv("DRONE_BUILD_DIR", "/var/cache/drone/github.com/drone/drone")
|
||||
f.WriteHost("127.0.0.1")
|
||||
f.WriteCmd("git clone --depth=0 --recursive --branch=master git://github.com/drone/drone.git /var/cache/drone/github.com/drone/drone")
|
||||
f.WriteCmd("git fetch origin +refs/pull/123/head:refs/remotes/origin/pr/123")
|
||||
f.WriteCmd("git checkout -qf -b pr/123 origin/pr/123")
|
||||
|
||||
if string(script) != f.String() {
|
||||
t.Errorf("Expected build script value saved as %s, got %s", f.String(), script)
|
||||
}
|
||||
}
|
49
pkg/build/buildfile/buildfile_test.go
Normal file
49
pkg/build/buildfile/buildfile_test.go
Normal file
|
@ -0,0 +1,49 @@
|
|||
package buildfile
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestWrite(t *testing.T) {
|
||||
|
||||
var f = New()
|
||||
var got, want = f.String(), base
|
||||
if got != want {
|
||||
t.Errorf("Exepected New() returned %s, got %s", want, got)
|
||||
}
|
||||
|
||||
f = &Buildfile{}
|
||||
f.WriteCmd("echo hi")
|
||||
got, want = f.String(), "echo '#DRONE:6563686f206869'\necho hi\n"
|
||||
if got != want {
|
||||
t.Errorf("Exepected WriteCmd returned %s, got %s", want, got)
|
||||
}
|
||||
|
||||
f = &Buildfile{}
|
||||
f.WriteCmdSilent("echo hi")
|
||||
got, want = f.String(), "echo hi\n"
|
||||
if got != want {
|
||||
t.Errorf("Exepected WriteCmdSilent returned %s, got %s", want, got)
|
||||
}
|
||||
|
||||
f = &Buildfile{}
|
||||
f.WriteComment("this is a comment")
|
||||
got, want = f.String(), "#this is a comment\n"
|
||||
if got != want {
|
||||
t.Errorf("Exepected WriteComment returned %s, got %s", want, got)
|
||||
}
|
||||
|
||||
f = &Buildfile{}
|
||||
f.WriteEnv("FOO", "BAR")
|
||||
got, want = f.String(), "export FOO=BAR\n"
|
||||
if got != want {
|
||||
t.Errorf("Exepected WriteEnv returned %s, got %s", want, got)
|
||||
}
|
||||
|
||||
f = &Buildfile{}
|
||||
f.WriteHost("127.0.0.1")
|
||||
got, want = f.String(), "[ -f /usr/bin/sudo ] || echo \"127.0.0.1\" | tee -a /etc/hosts\n[ -f /usr/bin/sudo ] && echo \"127.0.0.1\" | sudo tee -a /etc/hosts\n"
|
||||
if got != want {
|
||||
t.Errorf("Exepected WriteHost returned %s, got %s", want, got)
|
||||
}
|
||||
}
|
63
pkg/build/dockerfile/dockerfile_test.go
Normal file
63
pkg/build/dockerfile/dockerfile_test.go
Normal file
|
@ -0,0 +1,63 @@
|
|||
package dockerfile
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestWrite(t *testing.T) {
|
||||
|
||||
var f = New("ubuntu")
|
||||
var got, want = f.String(), "FROM ubuntu\n"
|
||||
if got != want {
|
||||
t.Errorf("Exepected New() returned %s, got %s", want, got)
|
||||
}
|
||||
|
||||
f = &Dockerfile{}
|
||||
f.WriteAdd("src", "target")
|
||||
got, want = f.String(), "ADD src target\n"
|
||||
if got != want {
|
||||
t.Errorf("Exepected WriteAdd returned %s, got %s", want, got)
|
||||
}
|
||||
|
||||
f = &Dockerfile{}
|
||||
f.WriteFrom("ubuntu")
|
||||
got, want = f.String(), "FROM ubuntu\n"
|
||||
if got != want {
|
||||
t.Errorf("Exepected WriteFrom returned %s, got %s", want, got)
|
||||
}
|
||||
|
||||
f = &Dockerfile{}
|
||||
f.WriteRun("whoami")
|
||||
got, want = f.String(), "RUN whoami\n"
|
||||
if got != want {
|
||||
t.Errorf("Exepected WriteRun returned %s, got %s", want, got)
|
||||
}
|
||||
|
||||
f = &Dockerfile{}
|
||||
f.WriteUser("root")
|
||||
got, want = f.String(), "USER root\n"
|
||||
if got != want {
|
||||
t.Errorf("Exepected WriteUser returned %s, got %s", want, got)
|
||||
}
|
||||
|
||||
f = &Dockerfile{}
|
||||
f.WriteEnv("FOO", "BAR")
|
||||
got, want = f.String(), "ENV FOO BAR\n"
|
||||
if got != want {
|
||||
t.Errorf("Exepected WriteEnv returned %s, got %s", want, got)
|
||||
}
|
||||
|
||||
f = &Dockerfile{}
|
||||
f.WriteWorkdir("/home/ubuntu")
|
||||
got, want = f.String(), "WORKDIR /home/ubuntu\n"
|
||||
if got != want {
|
||||
t.Errorf("Exepected WriteWorkdir returned %s, got %s", want, got)
|
||||
}
|
||||
|
||||
f = &Dockerfile{}
|
||||
f.WriteEntrypoint("/root")
|
||||
got, want = f.String(), "ENTRYPOINT /root\n"
|
||||
if got != want {
|
||||
t.Errorf("Exepected WriteEntrypoint returned %s, got %s", want, got)
|
||||
}
|
||||
}
|
|
@ -100,7 +100,7 @@ func Setup() {
|
|||
database.SaveMember(user1.ID, team2.ID, RoleOwner)
|
||||
database.SaveMember(user2.ID, team2.ID, RoleAdmin)
|
||||
database.SaveMember(user3.ID, team2.ID, RoleWrite)
|
||||
database.SaveMember(user1.ID, team3.ID, RoleOwner)
|
||||
database.SaveMember(user1.ID, team3.ID, RoleRead)
|
||||
|
||||
// create dummy repo data
|
||||
repo1 := Repo{
|
||||
|
|
|
@ -2,7 +2,6 @@ package handler
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/drone/drone/pkg/channel"
|
||||
|
@ -87,7 +86,7 @@ func RepoCreateGithub(w http.ResponseWriter, r *http.Request, u *User) error {
|
|||
client.ApiUrl = settings.GitHubApiUrl
|
||||
githubRepo, err := client.Repos.Find(owner, name)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("Unable to find GitHub repository %s/%s.", owner, name)
|
||||
}
|
||||
|
||||
repo, err := NewGitHubRepo(settings.GitHubDomain, owner, name, githubRepo.Private)
|
||||
|
@ -104,13 +103,12 @@ func RepoCreateGithub(w http.ResponseWriter, r *http.Request, u *User) error {
|
|||
if len(teamName) > 0 {
|
||||
team, err := database.GetTeamSlug(teamName)
|
||||
if err != nil {
|
||||
log.Printf("error retrieving team %s", teamName)
|
||||
return err
|
||||
return fmt.Errorf("Unable to find Team %s.", teamName)
|
||||
}
|
||||
|
||||
// user must be an admin member of the team
|
||||
if ok, _ := database.IsMemberAdmin(u.ID, team.ID); !ok {
|
||||
return fmt.Errorf("Forbidden")
|
||||
return fmt.Errorf("Invalid permission to access Team %s.", teamName)
|
||||
}
|
||||
|
||||
repo.TeamID = team.ID
|
||||
|
@ -125,7 +123,7 @@ func RepoCreateGithub(w http.ResponseWriter, r *http.Request, u *User) error {
|
|||
// create the github key, or update if one already exists
|
||||
_, err := client.RepoKeys.CreateUpdate(owner, name, repo.PublicKey, keyName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Unable to add Public Key to your GitHub repository")
|
||||
return fmt.Errorf("Unable to add Public Key to your GitHub repository.")
|
||||
}
|
||||
} else {
|
||||
|
||||
|
@ -137,13 +135,12 @@ func RepoCreateGithub(w http.ResponseWriter, r *http.Request, u *User) error {
|
|||
|
||||
// add the hook
|
||||
if _, err := client.Hooks.CreateUpdate(owner, name, link); err != nil {
|
||||
return fmt.Errorf("Unable to add Hook to your GitHub repository. %s", err.Error())
|
||||
return fmt.Errorf("Unable to add Hook to your GitHub repository.")
|
||||
}
|
||||
|
||||
// Save to the database
|
||||
if err := database.SaveRepo(repo); err != nil {
|
||||
log.Print("error saving new repository to the database")
|
||||
return err
|
||||
return fmt.Errorf("Error saving repository to the database. %s", err)
|
||||
}
|
||||
|
||||
return RenderText(w, http.StatusText(http.StatusOK), http.StatusOK)
|
||||
|
|
396
pkg/handler/testing/github_test.go
Normal file
396
pkg/handler/testing/github_test.go
Normal file
|
@ -0,0 +1,396 @@
|
|||
package testing
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/drone/drone/pkg/database"
|
||||
"github.com/drone/drone/pkg/handler"
|
||||
"github.com/drone/drone/pkg/model"
|
||||
|
||||
dbtest "github.com/drone/drone/pkg/database/testing"
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
// 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.")
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// this code should be refactored and centralized, but for now
|
||||
// it is just proof-of-concepting a testing strategy, so we'll
|
||||
// revisit later.
|
||||
|
||||
// mux is the HTTP request multiplexer used with the test server.
|
||||
var mux *http.ServeMux
|
||||
|
||||
// server is a test HTTP server used to provide mock API responses.
|
||||
var server *httptest.Server
|
||||
|
||||
func SetupFixtures() {
|
||||
dbtest.Setup()
|
||||
|
||||
// test server
|
||||
mux = http.NewServeMux()
|
||||
server = httptest.NewServer(mux)
|
||||
url, _ := url.Parse(server.URL)
|
||||
|
||||
// set database to use a localhost url for GitHub
|
||||
settings := model.Settings{}
|
||||
settings.GitHubKey = "123"
|
||||
settings.GitHubSecret = "abc"
|
||||
settings.GitHubApiUrl = url.String() // normall would be "https://api.github.com"
|
||||
settings.GitHubDomain = url.Host // normally would be "github.com"
|
||||
settings.Scheme = url.Scheme
|
||||
settings.Domain = "localhost"
|
||||
database.SaveSettings(&settings)
|
||||
|
||||
// -----------------------------------------------------------------------------------
|
||||
// fixture to return a public repository and successfully
|
||||
// create a commit hook.
|
||||
|
||||
mux.HandleFunc("/repos/example/public", func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprint(w, `{
|
||||
"name": "public",
|
||||
"full_name": "example/public",
|
||||
"private": false
|
||||
}`)
|
||||
})
|
||||
|
||||
mux.HandleFunc("/repos/example/public/hooks", func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintf(w, `{
|
||||
"url": "https://api.github.com/repos/example/public/hooks/1",
|
||||
"name": "web",
|
||||
"events": [ "push", "pull_request" ],
|
||||
"id": 1
|
||||
}`)
|
||||
})
|
||||
|
||||
// -----------------------------------------------------------------------------------
|
||||
// fixture to return a private repository and successfully
|
||||
// create a commit hook and ssh deploy key
|
||||
|
||||
mux.HandleFunc("/repos/example/private", func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprint(w, `{
|
||||
"name": "private",
|
||||
"full_name": "example/private",
|
||||
"private": true
|
||||
}`)
|
||||
})
|
||||
|
||||
mux.HandleFunc("/repos/example/private/hooks", func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintf(w, `{
|
||||
"url": "https://api.github.com/repos/example/private/hooks/1",
|
||||
"name": "web",
|
||||
"events": [ "push", "pull_request" ],
|
||||
"id": 1
|
||||
}`)
|
||||
})
|
||||
|
||||
mux.HandleFunc("/repos/example/private/keys", func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintf(w, `{
|
||||
"id": 1,
|
||||
"key": "ssh-rsa AAA...",
|
||||
"url": "https://api.github.com/user/keys/1",
|
||||
"title": "octocat@octomac"
|
||||
}`)
|
||||
})
|
||||
|
||||
// -----------------------------------------------------------------------------------
|
||||
// fixture to return a not found when accessing a github repository.
|
||||
|
||||
mux.HandleFunc("/repos/example/notfound", func(w http.ResponseWriter, r *http.Request) {
|
||||
http.NotFound(w, r)
|
||||
})
|
||||
|
||||
// -----------------------------------------------------------------------------------
|
||||
// fixture to return a public repository and successfully
|
||||
// create a commit hook.
|
||||
|
||||
mux.HandleFunc("/repos/example/hookerr", func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprint(w, `{
|
||||
"name": "hookerr",
|
||||
"full_name": "example/hookerr",
|
||||
"private": false
|
||||
}`)
|
||||
})
|
||||
|
||||
mux.HandleFunc("/repos/example/hookerr/hooks", func(w http.ResponseWriter, r *http.Request) {
|
||||
http.Error(w, "Forbidden", http.StatusForbidden)
|
||||
})
|
||||
|
||||
// -----------------------------------------------------------------------------------
|
||||
// fixture to return a private repository and successfully
|
||||
// create a commit hook and ssh deploy key
|
||||
|
||||
mux.HandleFunc("/repos/example/keyerr", func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprint(w, `{
|
||||
"name": "keyerr",
|
||||
"full_name": "example/keyerr",
|
||||
"private": true
|
||||
}`)
|
||||
})
|
||||
|
||||
mux.HandleFunc("/repos/example/keyerr/hooks", func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintf(w, `{
|
||||
"url": "https://api.github.com/repos/example/keyerr/hooks/1",
|
||||
"name": "web",
|
||||
"events": [ "push", "pull_request" ],
|
||||
"id": 1
|
||||
}`)
|
||||
})
|
||||
|
||||
mux.HandleFunc("/repos/example/keyerr/keys", func(w http.ResponseWriter, r *http.Request) {
|
||||
http.Error(w, "Forbidden", http.StatusForbidden)
|
||||
})
|
||||
|
||||
// -----------------------------------------------------------------------------------
|
||||
// fixture to return a public repository and successfully to
|
||||
// test adding a team.
|
||||
|
||||
mux.HandleFunc("/repos/example/team", func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprint(w, `{
|
||||
"name": "team",
|
||||
"full_name": "example/team",
|
||||
"private": false
|
||||
}`)
|
||||
})
|
||||
|
||||
mux.HandleFunc("/repos/example/team/hooks", func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintf(w, `{
|
||||
"url": "https://api.github.com/repos/example/team/hooks/1",
|
||||
"name": "web",
|
||||
"events": [ "push", "pull_request" ],
|
||||
"id": 1
|
||||
}`)
|
||||
})
|
||||
}
|
||||
|
||||
func TeardownFixtures() {
|
||||
dbtest.Teardown()
|
||||
server.Close()
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
// response for querying a repo
|
||||
var repoGet = `{
|
||||
"name": "Hello-World",
|
||||
"full_name": "octocat/Hello-World",
|
||||
"owner": {
|
||||
"login": "octocat"
|
||||
},
|
||||
"private": false,
|
||||
"git_url": "git://github.com/octocat/Hello-World.git",
|
||||
"ssh_url": "git@github.com:octocat/Hello-World.git",
|
||||
"clone_url": "https://github.com/octocat/Hello-World.git"
|
||||
}`
|
||||
|
||||
// response for querying a private repo
|
||||
var repoPrivateGet = `{
|
||||
"name": "Hello-World",
|
||||
"full_name": "octocat/Hello-World",
|
||||
"owner": {
|
||||
"login": "octocat"
|
||||
},
|
||||
"private": true,
|
||||
"git_url": "git://github.com/octocat/Hello-World.git",
|
||||
"ssh_url": "git@github.com:octocat/Hello-World.git",
|
||||
"clone_url": "https://github.com/octocat/Hello-World.git"
|
||||
}`
|
||||
|
||||
// response for creating a key
|
||||
var keyAdd = `
|
||||
{
|
||||
"id": 1,
|
||||
"key": "ssh-rsa AAA...",
|
||||
"url": "https://api.github.com/user/keys/1",
|
||||
"title": "octocat@octomac"
|
||||
}
|
||||
`
|
||||
|
||||
// response for creating a hook
|
||||
var hookAdd = `
|
||||
{
|
||||
"url": "https://api.github.com/repos/octocat/Hello-World/hooks/1",
|
||||
"updated_at": "2011-09-06T20:39:23Z",
|
||||
"created_at": "2011-09-06T17:26:27Z",
|
||||
"name": "web",
|
||||
"events": [
|
||||
"push",
|
||||
"pull_request"
|
||||
],
|
||||
"active": true,
|
||||
"config": {
|
||||
"url": "http://example.com",
|
||||
"content_type": "json"
|
||||
},
|
||||
"id": 1
|
||||
}
|
||||
`
|
||||
*/
|
Loading…
Reference in a new issue