You've already forked woodpecker
							
							
				mirror of
				https://github.com/woodpecker-ci/woodpecker.git
				synced 2025-10-30 23:27:39 +02:00 
			
		
		
		
	more work on the command line utility
This commit is contained in:
		
							
								
								
									
										2
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
									
									
									
									
								
							| @@ -13,7 +13,7 @@ test: | ||||
| 	go test -cover -short ./... | ||||
|  | ||||
| build: | ||||
| 	go build -o debian/drone/usr/local/bin/drone  -ldflags "-X main.revision $(SHA)" github.com/drone/drone/client | ||||
| 	go build -o debian/drone/usr/local/bin/drone  -ldflags "-X main.revision $(SHA)" github.com/drone/drone/cmd | ||||
| 	go build -o debian/drone/usr/local/bin/droned -ldflags "-X main.revision $(SHA)" github.com/drone/drone/server | ||||
|  | ||||
| install: | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| package main | ||||
| package client | ||||
| 
 | ||||
| import ( | ||||
| 	"bytes" | ||||
| @@ -10,6 +10,27 @@ import ( | ||||
| 	"strconv" | ||||
| ) | ||||
| 
 | ||||
| type Client struct { | ||||
| 	token string | ||||
| 	url   string | ||||
| 
 | ||||
| 	Commits *CommitService | ||||
| 	Repos   *RepoService | ||||
| 	Users   *UserService | ||||
| } | ||||
| 
 | ||||
| func New(token, url string) *Client { | ||||
| 	c := Client{ | ||||
| 		token: token, | ||||
| 		url:   url, | ||||
| 	} | ||||
| 
 | ||||
| 	c.Commits = &CommitService{&c} | ||||
| 	c.Repos = &RepoService{&c} | ||||
| 	c.Users = &UserService{&c} | ||||
| 	return &c | ||||
| } | ||||
| 
 | ||||
| var ( | ||||
| 	ErrNotFound       = errors.New("Not Found") | ||||
| 	ErrForbidden      = errors.New("Forbidden") | ||||
| @@ -18,17 +39,12 @@ var ( | ||||
| 	ErrInternalServer = errors.New("Internal Server Error") | ||||
| ) | ||||
| 
 | ||||
| type Client struct { | ||||
| 	Token string | ||||
| 	URL   string | ||||
| } | ||||
| 
 | ||||
| // Do submits an http.Request and parses the JSON-encoded http.Response, | ||||
| // runs an http.Request and parses the JSON-encoded http.Response, | ||||
| // storing the result in the value pointed to by v. | ||||
| func (c *Client) Do(method, path string, in, out interface{}) error { | ||||
| func (c *Client) run(method, path string, in, out interface{}) error { | ||||
| 
 | ||||
| 	// create the URI | ||||
| 	uri, err := url.Parse(c.URL + path) | ||||
| 	uri, err := url.Parse(c.url + path) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| @@ -37,9 +53,9 @@ func (c *Client) Do(method, path string, in, out interface{}) error { | ||||
| 		uri.Scheme = "http" | ||||
| 	} | ||||
| 
 | ||||
| 	if len(c.Token) > 0 { | ||||
| 	if len(c.token) > 0 { | ||||
| 		params := uri.Query() | ||||
| 		params.Add("access_token", c.Token) | ||||
| 		params.Add("access_token", c.token) | ||||
| 		uri.RawQuery = params.Encode() | ||||
| 	} | ||||
| 
 | ||||
| @@ -102,3 +118,36 @@ func (c *Client) Do(method, path string, in, out interface{}) error { | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // do makes an http.Request and returns the response | ||||
| func (c *Client) do(method, path string) (*http.Response, error) { | ||||
| 
 | ||||
| 	// create the URI | ||||
| 	uri, err := url.Parse(c.url + path) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	if len(uri.Scheme) == 0 { | ||||
| 		uri.Scheme = "http" | ||||
| 	} | ||||
| 
 | ||||
| 	if len(c.token) > 0 { | ||||
| 		params := uri.Query() | ||||
| 		params.Add("access_token", c.token) | ||||
| 		uri.RawQuery = params.Encode() | ||||
| 	} | ||||
| 
 | ||||
| 	// create the request | ||||
| 	req := &http.Request{ | ||||
| 		URL:           uri, | ||||
| 		Method:        method, | ||||
| 		ProtoMajor:    1, | ||||
| 		ProtoMinor:    1, | ||||
| 		Close:         true, | ||||
| 		ContentLength: 0, | ||||
| 	} | ||||
| 
 | ||||
| 	// make the request using the default http client | ||||
| 	return http.DefaultClient.Do(req) | ||||
| } | ||||
							
								
								
									
										52
									
								
								client/commits.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								client/commits.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | ||||
| package client | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"io" | ||||
|  | ||||
| 	"github.com/drone/drone/shared/model" | ||||
| ) | ||||
|  | ||||
| type CommitService struct { | ||||
| 	*Client | ||||
| } | ||||
|  | ||||
| // GET /v1/repos/{host}/{owner}/{name}/branch/{branch}/commit/{commit} | ||||
| func (s *CommitService) Get(host, owner, name, branch, sha string) (*model.Commit, error) { | ||||
| 	var path = fmt.Sprintf("/v1/repos/%s/%s/%s/branch/%s/commit/%s", host, owner, name, branch, sha) | ||||
| 	var commit = model.Commit{} | ||||
| 	var err = s.run("GET", path, nil, &commit) | ||||
| 	return &commit, err | ||||
| } | ||||
|  | ||||
| // GET /v1/repos/{host}/{owner}/{name}/branches/{branch}/commits/{commit}/console | ||||
| func (s *CommitService) GetOutput(host, owner, name, branch, sha string) (io.ReadCloser, error) { | ||||
| 	var path = fmt.Sprintf("/v1/repos/%s/%s/%s/branch/%s/commit/%s/console", host, owner, name, branch, sha) | ||||
| 	resp, err := s.do("GET", path) | ||||
| 	if err != nil { | ||||
| 		return nil, nil | ||||
| 	} | ||||
| 	return resp.Body, nil | ||||
| } | ||||
|  | ||||
| // POST /v1/repos/{host}/{owner}/{name}/branches/{branch}/commits/{commit}?action=rebuild | ||||
| func (s *CommitService) Rebuild(host, owner, name, branch, sha string) error { | ||||
| 	var path = fmt.Sprintf("/v1/repos/%s/%s/%s/branch/%s/commit/%s", host, owner, name, branch, sha) | ||||
| 	return s.run("POST", path, nil, nil) | ||||
| } | ||||
|  | ||||
| // GET /v1/repos/{host}/{owner}/{name}/feed | ||||
| func (s *CommitService) List(host, owner, name string) ([]*model.Commit, error) { | ||||
| 	var path = fmt.Sprintf("/v1/repos/%s/%s/%s/feed", host, owner, name) | ||||
| 	var list []*model.Commit | ||||
| 	var err = s.run("GET", path, nil, &list) | ||||
| 	return list, err | ||||
| } | ||||
|  | ||||
| // GET /v1/repos/{host}/{owner}/{name}/branch/{branch} | ||||
| func (s *CommitService) ListBranch(host, owner, name, branch string) ([]*model.Commit, error) { | ||||
| 	var path = fmt.Sprintf("/v1/repos/%s/%s/%s/branch/%s", host, owner, name, branch) | ||||
| 	var list []*model.Commit | ||||
| 	var err = s.run("GET", path, nil, &list) | ||||
| 	return list, err | ||||
| } | ||||
							
								
								
									
										314
									
								
								client/main.go
									
									
									
									
									
								
							
							
						
						
									
										314
									
								
								client/main.go
									
									
									
									
									
								
							| @@ -1,314 +0,0 @@ | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"flag" | ||||
| 	"fmt" | ||||
| 	"io/ioutil" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"sync" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/drone/drone/shared/build" | ||||
| 	"github.com/drone/drone/shared/build/docker" | ||||
| 	"github.com/drone/drone/shared/build/log" | ||||
| 	"github.com/drone/drone/shared/build/repo" | ||||
| 	"github.com/drone/drone/shared/build/script" | ||||
|  | ||||
| 	"gopkg.in/yaml.v1" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	// identity file (id_rsa) that will be injected | ||||
| 	// into the container if specified | ||||
| 	identity = flag.String("identity", "", "") | ||||
|  | ||||
| 	// runs Drone in parallel mode if True | ||||
| 	parallel = flag.Bool("parallel", false, "") | ||||
|  | ||||
| 	// build will timeout after N milliseconds. | ||||
| 	// this will default to 500 minutes (6 hours) | ||||
| 	timeout = flag.Duration("timeout", 300*time.Minute, "") | ||||
|  | ||||
| 	// build will run in a privileged container | ||||
| 	privileged = flag.Bool("privileged", false, "") | ||||
|  | ||||
| 	// runs Drone with verbose output if True | ||||
| 	verbose = flag.Bool("v", false, "") | ||||
|  | ||||
| 	// displays the help / usage if True | ||||
| 	help = flag.Bool("h", false, "") | ||||
|  | ||||
| 	// version number, currently deterined by the | ||||
| 	// git revision number (sha) | ||||
| 	version string | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	// default logging | ||||
| 	log.SetPrefix("\033[2m[DRONE] ") | ||||
| 	log.SetSuffix("\033[0m\n") | ||||
| 	log.SetOutput(os.Stdout) | ||||
| 	log.SetPriority(log.LOG_NOTICE) | ||||
| 	docker.Logging = false | ||||
| } | ||||
|  | ||||
| func main() { | ||||
| 	// Parse the input parameters | ||||
| 	flag.Usage = usage | ||||
| 	flag.Parse() | ||||
|  | ||||
| 	if *help { | ||||
| 		flag.Usage() | ||||
| 		os.Exit(0) | ||||
| 	} | ||||
|  | ||||
| 	if *verbose { | ||||
| 		log.SetPriority(log.LOG_DEBUG) | ||||
| 	} | ||||
|  | ||||
| 	// Must speicify a command | ||||
| 	args := flag.Args() | ||||
| 	if len(args) == 0 { | ||||
| 		flag.Usage() | ||||
| 		os.Exit(0) | ||||
| 	} | ||||
|  | ||||
| 	switch { | ||||
| 	// run drone build assuming the current | ||||
| 	// working directory contains the drone.yml | ||||
| 	case args[0] == "build" && len(args) == 1: | ||||
| 		path, _ := os.Getwd() | ||||
| 		path = filepath.Join(path, ".drone.yml") | ||||
| 		run(path) | ||||
|  | ||||
| 	// run drone build where the path to the | ||||
| 	// source directory is provided | ||||
| 	case args[0] == "build" && len(args) == 2: | ||||
| 		path := args[1] | ||||
| 		path = filepath.Clean(path) | ||||
| 		path, _ = filepath.Abs(path) | ||||
| 		path = filepath.Join(path, ".drone.yml") | ||||
| 		run(path) | ||||
|  | ||||
| 	// run drone vet where the path to the | ||||
| 	// source directory is provided | ||||
| 	case args[0] == "vet" && len(args) == 2: | ||||
| 		path := args[1] | ||||
| 		path = filepath.Clean(path) | ||||
| 		path, _ = filepath.Abs(path) | ||||
| 		path = filepath.Join(path, ".drone.yml") | ||||
| 		vet(path) | ||||
|  | ||||
| 	// run drone vet assuming the current | ||||
| 	// working directory contains the drone.yml | ||||
| 	case args[0] == "vet" && len(args) == 1: | ||||
| 		path, _ := os.Getwd() | ||||
| 		path = filepath.Join(path, ".drone.yml") | ||||
| 		vet(path) | ||||
|  | ||||
| 	// print the version / revision number | ||||
| 	case args[0] == "version" && len(args) == 1: | ||||
| 		println(version) | ||||
|  | ||||
| 	// print the help message | ||||
| 	case args[0] == "help" && len(args) == 1: | ||||
| 		flag.Usage() | ||||
| 	} | ||||
|  | ||||
| 	os.Exit(0) | ||||
| } | ||||
|  | ||||
| func vet(path string) { | ||||
| 	// parse the Drone yml file | ||||
| 	script, err := script.ParseBuildFile(path) | ||||
| 	if err != nil { | ||||
| 		log.Err(err.Error()) | ||||
| 		os.Exit(1) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// print the Drone yml as parsed | ||||
| 	out, _ := yaml.Marshal(script) | ||||
| 	log.Noticef("parsed yaml:\n%s", string(out)) | ||||
| } | ||||
|  | ||||
| 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 | ||||
| 	} | ||||
|  | ||||
| 	// remove deploy & publish sections | ||||
| 	// for now, until I fix bug | ||||
| 	s.Publish = nil | ||||
| 	s.Deploy = nil | ||||
|  | ||||
| 	// get the repository root directory | ||||
| 	dir := filepath.Dir(path) | ||||
| 	code := repo.Repo{ | ||||
| 		Name:   filepath.Base(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 | ||||
| 		builder.Privileged = *privileged | ||||
|  | ||||
| 		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) | ||||
| } | ||||
|  | ||||
| func runSequential(builders []*build.Builder) { | ||||
| 	// loop through and execute each build | ||||
| 	for _, builder := range builders { | ||||
| 		if err := builder.Run(); err != nil { | ||||
| 			log.Errf("Error executing build: %s", err.Error()) | ||||
| 			os.Exit(1) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func runParallel(builders []*build.Builder) { | ||||
| 	// spawn four worker goroutines | ||||
| 	var wg sync.WaitGroup | ||||
| 	for _, builder := range builders { | ||||
| 		// Increment the WaitGroup counter | ||||
| 		wg.Add(1) | ||||
| 		// Launch a goroutine to run the build | ||||
| 		go func(builder *build.Builder) { | ||||
| 			defer wg.Done() | ||||
| 			builder.Run() | ||||
| 		}(builder) | ||||
| 		time.Sleep(500 * time.Millisecond) // get weird iptables failures unless we sleep. | ||||
| 	} | ||||
|  | ||||
| 	// wait for the workers to finish | ||||
| 	wg.Wait() | ||||
| } | ||||
|  | ||||
| var usage = func() { | ||||
| 	fmt.Println(`Drone is a tool for building and testing code in Docker containers. | ||||
|  | ||||
| Usage: | ||||
|  | ||||
| 	drone command [arguments] | ||||
|  | ||||
| The commands are: | ||||
|  | ||||
|    build           build and test the repository | ||||
|    version         print the version number | ||||
|    vet             validate the yaml configuration file | ||||
|  | ||||
|   -v               runs drone with verbose output | ||||
|   -h               display this help and exit | ||||
|   --parallel       runs drone build tasks in parallel | ||||
|   --timeout=300ms  timeout build after 300 milliseconds | ||||
|   --privileged     runs drone build in a privileged container | ||||
|  | ||||
| Examples: | ||||
|   drone build                 builds the source in the pwd | ||||
|   drone build /path/to/repo   builds the source repository | ||||
|  | ||||
| Use "drone help [command]" for more information about a command. | ||||
| `) | ||||
| } | ||||
							
								
								
									
										46
									
								
								client/repos.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								client/repos.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | ||||
| package client | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	"github.com/drone/drone/shared/model" | ||||
| ) | ||||
|  | ||||
| type RepoService struct { | ||||
| 	*Client | ||||
| } | ||||
|  | ||||
| // GET /v1/repos/{host}/{owner}/{name} | ||||
| func (s *RepoService) Get() (*model.Repo, error) { | ||||
| 	var path = fmt.Sprintf("/v1/repos/%s/%s/%s") | ||||
| 	var repo = model.Repo{} | ||||
| 	var err = s.run("PUT", path, nil, &repo) | ||||
| 	return &repo, err | ||||
| } | ||||
|  | ||||
| // PUT /v1/repos/{host}/{owner}/{name} | ||||
| func (s *RepoService) Update(repo *model.Repo) (*model.Repo, error) { | ||||
| 	var path = fmt.Sprintf("/v1/repos/%s/%s/%s") | ||||
| 	var result = model.Repo{} | ||||
| 	var err = s.run("PUT", path, &repo, &result) | ||||
| 	return &result, err | ||||
| } | ||||
|  | ||||
| // POST /v1/repos/{host}/{owner}/{name} | ||||
| func (s *RepoService) Enable(host, owner, name string) error { | ||||
| 	var path = fmt.Sprintf("/v1/repos/%s/%s/%s", host, owner, name) | ||||
| 	return s.run("POST", path, nil, nil) | ||||
| } | ||||
|  | ||||
| // DELETE /v1/repos/{host}/{owner}/{name} | ||||
| func (s *RepoService) Disable(host, owner, name string) error { | ||||
| 	var path = fmt.Sprintf("/v1/repos/%s/%s/%s", host, owner, name) | ||||
| 	return s.run("DELETE", path, nil, nil) | ||||
| } | ||||
|  | ||||
| // GET /v1/user/repos | ||||
| func (s *RepoService) List() ([]*model.Repo, error) { | ||||
| 	var repos []*model.Repo | ||||
| 	var err = s.run("GET", "/v1/user/repos", nil, &repos) | ||||
| 	return repos, err | ||||
| } | ||||
							
								
								
									
										47
									
								
								client/users.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								client/users.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | ||||
| package client | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	"github.com/drone/drone/shared/model" | ||||
| ) | ||||
|  | ||||
| type UserService struct { | ||||
| 	*Client | ||||
| } | ||||
|  | ||||
| // GET /v1/users/{host}/{login} | ||||
| func (s *UserService) Get(remote, login string) (*model.User, error) { | ||||
| 	var path = fmt.Sprintf("/v1/users/%s/%s", remote, login) | ||||
| 	var user = model.User{} | ||||
| 	var err = s.run("GET", path, nil, &user) | ||||
| 	return &user, err | ||||
| } | ||||
|  | ||||
| // GET /v1/user | ||||
| func (s *UserService) GetCurrent() (*model.User, error) { | ||||
| 	var user = model.User{} | ||||
| 	var err = s.run("GET", "/v1/user", nil, &user) | ||||
| 	return &user, err | ||||
| } | ||||
|  | ||||
| // POST /v1/users/{host}/{login} | ||||
| func (s *UserService) Create(remote, login string) (*model.User, error) { | ||||
| 	var path = fmt.Sprintf("/v1/users/%s/%s", remote, login) | ||||
| 	var user = model.User{} | ||||
| 	var err = s.run("POST", path, nil, &user) | ||||
| 	return &user, err | ||||
| } | ||||
|  | ||||
| // DELETE /v1/users/{host}/{login} | ||||
| func (s *UserService) Delete(remote, login string) error { | ||||
| 	var path = fmt.Sprintf("/v1/users/%s/%s", remote, login) | ||||
| 	return s.run("DELETE", path, nil, nil) | ||||
| } | ||||
|  | ||||
| // GET /v1/users | ||||
| func (s *UserService) List() ([]*model.User, error) { | ||||
| 	var users []*model.User | ||||
| 	var err = s.run("GET", "/v1/users", nil, &users) | ||||
| 	return users, err | ||||
| } | ||||
| @@ -1,90 +0,0 @@ | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"regexp" | ||||
| 	"strings" | ||||
| 	"time" | ||||
| ) | ||||
|  | ||||
| // getGoPath checks the source codes absolute path | ||||
| // in reference to the host operating system's GOPATH | ||||
| // to correctly determine the code's package path. This | ||||
| // is Go-specific, since Go code must exist in | ||||
| // $GOPATH/src/github.com/{owner}/{name} | ||||
| func getGoPath(dir string) (string, bool) { | ||||
| 	path := os.Getenv("GOPATH") | ||||
| 	if len(path) == 0 { | ||||
| 		return "", false | ||||
| 	} | ||||
| 	// append src to the GOPATH, since | ||||
| 	// the code will be stored in the src dir | ||||
| 	path = filepath.Join(path, "src") | ||||
| 	if !filepath.HasPrefix(dir, path) { | ||||
| 		return "", false | ||||
| 	} | ||||
|  | ||||
| 	// remove the prefix from the directory | ||||
| 	// this should leave us with the go package name | ||||
| 	return dir[len(path):], true | ||||
| } | ||||
|  | ||||
| var gopathExp = regexp.MustCompile("./src/(github.com/[^/]+/[^/]+|bitbucket.org/[^/]+/[^/]+|code.google.com/[^/]+/[^/]+)") | ||||
|  | ||||
| // getRepoPath checks the source codes absolute path | ||||
| // on the host operating system in an attempt | ||||
| // to correctly determine the code's package path. This | ||||
| // is Go-specific, since Go code must exist in | ||||
| // $GOPATH/src/github.com/{owner}/{name} | ||||
| func getRepoPath(dir string) (path string, ok bool) { | ||||
| 	// let's get the package directory based | ||||
| 	// on the path in the host OS | ||||
| 	indexes := gopathExp.FindStringIndex(dir) | ||||
| 	if len(indexes) == 0 { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	index := indexes[len(indexes)-1] | ||||
|  | ||||
| 	// if the dir is /home/ubuntu/go/src/github.com/foo/bar | ||||
| 	// the index will start at /src/github.com/foo/bar. | ||||
| 	// We'll need to strip "/src/" which is where the | ||||
| 	// magic number 5 comes from. | ||||
| 	index = strings.LastIndex(dir, "/src/") | ||||
| 	return dir[index+5:], true | ||||
| } | ||||
|  | ||||
| // getGitOrigin checks the .git origin in an attempt | ||||
| // to correctly determine the code's package path. This | ||||
| // is Go-specific, since Go code must exist in | ||||
| // $GOPATH/src/github.com/{owner}/{name} | ||||
| func getGitOrigin(dir string) (path string, ok bool) { | ||||
| 	// TODO | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // prints the time as a human readable string | ||||
| func humanizeDuration(d time.Duration) string { | ||||
| 	if seconds := int(d.Seconds()); seconds < 1 { | ||||
| 		return "Less than a second" | ||||
| 	} else if seconds < 60 { | ||||
| 		return fmt.Sprintf("%d seconds", seconds) | ||||
| 	} else if minutes := int(d.Minutes()); minutes == 1 { | ||||
| 		return "About a minute" | ||||
| 	} else if minutes < 60 { | ||||
| 		return fmt.Sprintf("%d minutes", minutes) | ||||
| 	} else if hours := int(d.Hours()); hours == 1 { | ||||
| 		return "About an hour" | ||||
| 	} else if hours < 48 { | ||||
| 		return fmt.Sprintf("%d hours", hours) | ||||
| 	} else if hours < 24*7*2 { | ||||
| 		return fmt.Sprintf("%d days", hours/24) | ||||
| 	} else if hours < 24*30*3 { | ||||
| 		return fmt.Sprintf("%d weeks", hours/24/7) | ||||
| 	} else if hours < 24*365*2 { | ||||
| 		return fmt.Sprintf("%d months", hours/24/30) | ||||
| 	} | ||||
| 	return fmt.Sprintf("%f years", d.Hours()/24/365) | ||||
| } | ||||
| @@ -2,6 +2,7 @@ package main | ||||
|  | ||||
| import ( | ||||
| 	"github.com/codegangsta/cli" | ||||
| 	"github.com/drone/drone/client" | ||||
| ) | ||||
|  | ||||
| // NewDisableCommand returns the CLI command for "disable". | ||||
| @@ -17,18 +18,13 @@ func NewDisableCommand() cli.Command { | ||||
| } | ||||
|  | ||||
| // disableCommandFunc executes the "disable" command. | ||||
| func disableCommandFunc(c *cli.Context, client *Client) error { | ||||
| 	var repo string | ||||
| 	var arg = c.Args() | ||||
| func disableCommandFunc(c *cli.Context, client *client.Client) error { | ||||
| 	var host, owner, name string | ||||
| 	var args = c.Args() | ||||
|  | ||||
| 	if len(arg) != 0 { | ||||
| 		repo = arg[0] | ||||
| 	if len(args) != 0 { | ||||
| 		host, owner, name = parseRepo(args[0]) | ||||
| 	} | ||||
|  | ||||
| 	err := client.Do("DELETE", "/v1/repos/"+repo, nil, nil) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| 	return client.Repos.Disable(host, owner, name) | ||||
| } | ||||
|   | ||||
| @@ -2,6 +2,7 @@ package main | ||||
|  | ||||
| import ( | ||||
| 	"github.com/codegangsta/cli" | ||||
| 	"github.com/drone/drone/client" | ||||
| ) | ||||
|  | ||||
| // NewEnableCommand returns the CLI command for "enable". | ||||
| @@ -17,18 +18,13 @@ func NewEnableCommand() cli.Command { | ||||
| } | ||||
|  | ||||
| // enableCommandFunc executes the "enable" command. | ||||
| func enableCommandFunc(c *cli.Context, client *Client) error { | ||||
| 	var repo string | ||||
| 	var arg = c.Args() | ||||
| func enableCommandFunc(c *cli.Context, client *client.Client) error { | ||||
| 	var host, owner, name string | ||||
| 	var args = c.Args() | ||||
|  | ||||
| 	if len(arg) != 0 { | ||||
| 		repo = arg[0] | ||||
| 	if len(args) != 0 { | ||||
| 		host, owner, name = parseRepo(args[0]) | ||||
| 	} | ||||
|  | ||||
| 	err := client.Do("POST", "/v1/repos/"+repo, nil, nil) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| 	return client.Repos.Enable(host, owner, name) | ||||
| } | ||||
|   | ||||
| @@ -4,25 +4,28 @@ import ( | ||||
| 	"os" | ||||
|  | ||||
| 	"github.com/codegangsta/cli" | ||||
| 	"github.com/drone/drone/client" | ||||
| ) | ||||
|  | ||||
| type handlerFunc func(*cli.Context, *Client) error | ||||
| type handlerFunc func(*cli.Context, *client.Client) error | ||||
|  | ||||
| // handle wraps the command function handlers and | ||||
| // sets up the environment. | ||||
| func handle(c *cli.Context, fn handlerFunc) { | ||||
| 	client := Client{} | ||||
| 	client.Token = os.Getenv("DRONE_TOKEN") | ||||
| 	client.URL = os.Getenv("DRONE_HOST") | ||||
| 	var token = c.GlobalString("token") | ||||
| 	var server = c.GlobalString("server") | ||||
|  | ||||
| 	// if no url is provided we can default | ||||
| 	// if no server url is provided we can default | ||||
| 	// to the hosted Drone service. | ||||
| 	if len(client.URL) == 0 { | ||||
| 		client.URL = "http://test.drone.io" | ||||
| 	if len(server) == 0 { | ||||
| 		server = "http://test.drone.io" | ||||
| 	} | ||||
|  | ||||
| 	// create the drone client | ||||
| 	client := client.New(token, server) | ||||
|  | ||||
| 	// handle the function | ||||
| 	if err := fn(c, &client); err != nil { | ||||
| 	if err := fn(c, client); err != nil { | ||||
| 		println(err.Error()) | ||||
| 		os.Exit(1) | ||||
| 	} | ||||
|   | ||||
							
								
								
									
										22
									
								
								cmd/main.go
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								cmd/main.go
									
									
									
									
									
								
							| @@ -5,11 +5,31 @@ import ( | ||||
| 	"os" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	// commit sha for the current build. | ||||
| 	version  string = "0.3-dev" | ||||
| 	revision string | ||||
| ) | ||||
|  | ||||
| func main() { | ||||
| 	app := cli.NewApp() | ||||
| 	app.Name = "drone" | ||||
| 	app.Version = "1.0" | ||||
| 	app.Version = version | ||||
| 	app.Usage = "command line utility" | ||||
| 	app.Flags = []cli.Flag{ | ||||
| 		cli.StringFlag{ | ||||
| 			Name:   "t, token", | ||||
| 			Value:  "", | ||||
| 			Usage:  "server auth token", | ||||
| 			EnvVar: "DRONE_TOKEN", | ||||
| 		}, | ||||
| 		cli.StringFlag{ | ||||
| 			Name:   "s, server", | ||||
| 			Value:  "", | ||||
| 			Usage:  "server location", | ||||
| 			EnvVar: "DRONE_SERVER", | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	app.Commands = []cli.Command{ | ||||
| 		NewBuildCommand(), | ||||
|   | ||||
| @@ -1,9 +1,8 @@ | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	"github.com/codegangsta/cli" | ||||
| 	"github.com/drone/drone/client" | ||||
| ) | ||||
|  | ||||
| // NewRestartCommand returns the CLI command for "restart". | ||||
| @@ -19,22 +18,19 @@ func NewRestartCommand() cli.Command { | ||||
| } | ||||
|  | ||||
| // restartCommandFunc executes the "restart" command. | ||||
| func restartCommandFunc(c *cli.Context, client *Client) error { | ||||
| 	var branch string = "master" | ||||
| 	var commit string | ||||
| 	var repo string | ||||
| 	var arg = c.Args() | ||||
| func restartCommandFunc(c *cli.Context, client *client.Client) error { | ||||
| 	var host, owner, repo, branch, sha string | ||||
| 	var args = c.Args() | ||||
|  | ||||
| 	switch len(arg) { | ||||
| 	case 2: | ||||
| 		repo = arg[0] | ||||
| 		commit = arg[1] | ||||
| 	case 3: | ||||
| 		repo = arg[0] | ||||
| 		branch = arg[1] | ||||
| 		commit = arg[2] | ||||
| 	if len(args) == 5 { | ||||
| 		host, owner, repo = parseRepo(args[0]) | ||||
| 	} else { | ||||
| 		host = "unknown" | ||||
| 		owner = "unknown" | ||||
| 		repo = "unknown" | ||||
| 		branch = "unknown" | ||||
| 		sha = "unknown" | ||||
| 	} | ||||
|  | ||||
| 	path := fmt.Sprintf("/v1/repos/%s/branches/%s/commits/%s?action=rebuild", repo, branch, commit) | ||||
| 	return client.Do("POST", path, nil, nil) | ||||
| 	return client.Commits.Rebuild(host, owner, repo, branch, sha) | ||||
| } | ||||
|   | ||||
							
								
								
									
										14
									
								
								cmd/util.go
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								cmd/util.go
									
									
									
									
									
								
							| @@ -9,6 +9,20 @@ import ( | ||||
| 	"time" | ||||
| ) | ||||
|  | ||||
| func parseRepo(str string) (host, owner, repo string) { | ||||
| 	var parts = strings.Split(str, "/") | ||||
| 	if len(repo) != 3 { | ||||
| 		host = "undefined" | ||||
| 		owner = "undefined" | ||||
| 		repo = "undefined" | ||||
| 		return | ||||
| 	} | ||||
| 	host = parts[0] | ||||
| 	owner = parts[1] | ||||
| 	repo = parts[2] | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // getGoPath checks the source codes absolute path | ||||
| // in reference to the host operating system's GOPATH | ||||
| // to correctly determine the code's package path. This | ||||
|   | ||||
| @@ -4,7 +4,7 @@ import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	"github.com/codegangsta/cli" | ||||
| 	"github.com/drone/drone/shared/model" | ||||
| 	"github.com/drone/drone/client" | ||||
| ) | ||||
|  | ||||
| // NewWhoamiCommand returns the CLI command for "whoami". | ||||
| @@ -20,9 +20,8 @@ func NewWhoamiCommand() cli.Command { | ||||
| } | ||||
|  | ||||
| // whoamiCommandFunc executes the "logout" command. | ||||
| func whoamiCommandFunc(c *cli.Context, client *Client) error { | ||||
| 	user := model.User{} | ||||
| 	err := client.Do("GET", "/v1/user", nil, &user) | ||||
| func whoamiCommandFunc(c *cli.Context, client *client.Client) error { | ||||
| 	user, err := client.Users.GetCurrent() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user