mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2025-10-21 21:03:22 +00:00
moved cmd to cli folder
This commit is contained in:
164
cli/build.go
Normal file
164
cli/build.go
Normal file
@@ -0,0 +1,164 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"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"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
)
|
||||
|
||||
const EXIT_STATUS = 1
|
||||
|
||||
// NewBuildCommand returns the CLI command for "build".
|
||||
func NewBuildCommand() cli.Command {
|
||||
return cli.Command{
|
||||
Name: "build",
|
||||
Usage: "run a local build",
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "i",
|
||||
Value: "",
|
||||
Usage: "identify file injected in the container",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "p",
|
||||
Value: "false",
|
||||
Usage: "runs drone build in a privileged container",
|
||||
},
|
||||
},
|
||||
Action: func(c *cli.Context) {
|
||||
buildCommandFunc(c)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// buildCommandFunc executes the "build" command.
|
||||
func buildCommandFunc(c *cli.Context) {
|
||||
var privileged = c.Bool("p")
|
||||
var identity = c.String("i")
|
||||
var path string
|
||||
|
||||
// the path is provided as an optional argument that
|
||||
// will otherwise default to $PWD/.drone.yml
|
||||
if len(c.Args()) > 0 {
|
||||
path = c.Args()[0]
|
||||
}
|
||||
|
||||
switch len(path) {
|
||||
case 0:
|
||||
path, _ = os.Getwd()
|
||||
path = filepath.Join(path, ".drone.yml")
|
||||
default:
|
||||
path = filepath.Clean(path)
|
||||
path, _ = filepath.Abs(path)
|
||||
path = filepath.Join(path, ".drone.yml")
|
||||
}
|
||||
|
||||
// this configures the default Docker logging levels,
|
||||
// and suffix and prefix values.
|
||||
log.SetPrefix("\033[2m[DRONE] ")
|
||||
log.SetSuffix("\033[0m\n")
|
||||
log.SetOutput(os.Stdout)
|
||||
log.SetPriority(log.LOG_DEBUG) //LOG_NOTICE
|
||||
docker.Logging = false
|
||||
|
||||
var exit, _ = run(path, identity, privileged)
|
||||
os.Exit(exit)
|
||||
}
|
||||
|
||||
func run(path, identity string, privileged bool) (int, error) {
|
||||
dockerClient := docker.New()
|
||||
|
||||
// parse the Drone yml file
|
||||
s, err := script.ParseBuildFile(path)
|
||||
if err != nil {
|
||||
log.Err(err.Error())
|
||||
return EXIT_STATUS, err
|
||||
}
|
||||
|
||||
// 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))
|
||||
|
||||
// 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)
|
||||
return EXIT_STATUS, err
|
||||
}
|
||||
}
|
||||
|
||||
// loop through and create builders
|
||||
builder := build.New(dockerClient)
|
||||
builder.Build = s
|
||||
builder.Repo = &code
|
||||
builder.Key = key
|
||||
builder.Stdout = os.Stdout
|
||||
// TODO ADD THIS BACK
|
||||
builder.Timeout = 300 * time.Minute
|
||||
builder.Privileged = privileged
|
||||
|
||||
// execute the build
|
||||
if err := builder.Run(); err != nil {
|
||||
log.Errf("Error executing build: %s", err.Error())
|
||||
return EXIT_STATUS, err
|
||||
}
|
||||
|
||||
fmt.Printf("\nDrone Build Results \033[90m(%s)\033[0m\n", dir)
|
||||
|
||||
// loop through and print results
|
||||
|
||||
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))
|
||||
}
|
||||
|
||||
return builder.BuildState.ExitCode, nil
|
||||
}
|
30
cli/disable.go
Normal file
30
cli/disable.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/drone/drone/client"
|
||||
)
|
||||
|
||||
// NewDisableCommand returns the CLI command for "disable".
|
||||
func NewDisableCommand() cli.Command {
|
||||
return cli.Command{
|
||||
Name: "disable",
|
||||
Usage: "disable a repository",
|
||||
Flags: []cli.Flag{},
|
||||
Action: func(c *cli.Context) {
|
||||
handle(c, disableCommandFunc)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// disableCommandFunc executes the "disable" command.
|
||||
func disableCommandFunc(c *cli.Context, client *client.Client) error {
|
||||
var host, owner, name string
|
||||
var args = c.Args()
|
||||
|
||||
if len(args) != 0 {
|
||||
host, owner, name = parseRepo(args[0])
|
||||
}
|
||||
|
||||
return client.Repos.Disable(host, owner, name)
|
||||
}
|
30
cli/enable.go
Normal file
30
cli/enable.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/drone/drone/client"
|
||||
)
|
||||
|
||||
// NewEnableCommand returns the CLI command for "enable".
|
||||
func NewEnableCommand() cli.Command {
|
||||
return cli.Command{
|
||||
Name: "enable",
|
||||
Usage: "enable a repository",
|
||||
Flags: []cli.Flag{},
|
||||
Action: func(c *cli.Context) {
|
||||
handle(c, enableCommandFunc)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// enableCommandFunc executes the "enable" command.
|
||||
func enableCommandFunc(c *cli.Context, client *client.Client) error {
|
||||
var host, owner, name string
|
||||
var args = c.Args()
|
||||
|
||||
if len(args) != 0 {
|
||||
host, owner, name = parseRepo(args[0])
|
||||
}
|
||||
|
||||
return client.Repos.Enable(host, owner, name)
|
||||
}
|
32
cli/handle.go
Normal file
32
cli/handle.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/drone/drone/client"
|
||||
)
|
||||
|
||||
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) {
|
||||
var token = c.GlobalString("token")
|
||||
var server = c.GlobalString("server")
|
||||
|
||||
// if no server url is provided we can default
|
||||
// to the hosted Drone service.
|
||||
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 {
|
||||
println(err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
45
cli/main.go
Normal file
45
cli/main.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/codegangsta/cli"
|
||||
"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 = 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(),
|
||||
NewReposCommand(),
|
||||
NewStatusCommand(),
|
||||
NewEnableCommand(),
|
||||
NewDisableCommand(),
|
||||
NewRestartCommand(),
|
||||
NewWhoamiCommand(),
|
||||
}
|
||||
|
||||
app.Run(os.Args)
|
||||
}
|
43
cli/repos.go
Normal file
43
cli/repos.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/drone/drone/client"
|
||||
)
|
||||
|
||||
// NewReposCommand returns the CLI command for "repos".
|
||||
func NewReposCommand() cli.Command {
|
||||
return cli.Command{
|
||||
Name: "repos",
|
||||
Usage: "lists active remote repositories",
|
||||
Flags: []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "a, all",
|
||||
Usage: "list all repositories",
|
||||
},
|
||||
},
|
||||
Action: func(c *cli.Context) {
|
||||
handle(c, reposCommandFunc)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// reposCommandFunc executes the "repos" command.
|
||||
func reposCommandFunc(c *cli.Context, client *client.Client) error {
|
||||
repos, err := client.Repos.List()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var all = c.Bool("a")
|
||||
for _, repo := range repos {
|
||||
if !all && !repo.Active {
|
||||
continue
|
||||
}
|
||||
|
||||
fmt.Printf("%s/%s/%s\n", repo.Host, repo.Owner, repo.Name)
|
||||
}
|
||||
return nil
|
||||
}
|
39
cli/restart.go
Normal file
39
cli/restart.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/drone/drone/client"
|
||||
)
|
||||
|
||||
// NewRestartCommand returns the CLI command for "restart".
|
||||
func NewRestartCommand() cli.Command {
|
||||
return cli.Command{
|
||||
Name: "restart",
|
||||
Usage: "restarts a build on the server",
|
||||
Flags: []cli.Flag{},
|
||||
Action: func(c *cli.Context) {
|
||||
handle(c, restartCommandFunc)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// restartCommandFunc executes the "restart" command.
|
||||
func restartCommandFunc(c *cli.Context, client *client.Client) error {
|
||||
var host, owner, repo, branch, sha string
|
||||
var args = c.Args()
|
||||
|
||||
if len(args) != 0 {
|
||||
host, owner, repo = parseRepo(args[0])
|
||||
}
|
||||
|
||||
switch len(args) {
|
||||
case 2:
|
||||
branch = "master"
|
||||
sha = args[1]
|
||||
case 3,4,5:
|
||||
branch = args[1]
|
||||
sha = args[2]
|
||||
}
|
||||
|
||||
return client.Commits.Rebuild(host, owner, repo, branch, sha)
|
||||
}
|
52
cli/status.go
Normal file
52
cli/status.go
Normal file
@@ -0,0 +1,52 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/drone/drone/client"
|
||||
)
|
||||
|
||||
// NewStatusCommand returns the CLI command for "status".
|
||||
func NewStatusCommand() cli.Command {
|
||||
return cli.Command{
|
||||
Name: "status",
|
||||
Usage: "display a repository build status",
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "b, branch",
|
||||
Usage: "branch to display",
|
||||
},
|
||||
},
|
||||
Action: func(c *cli.Context) {
|
||||
handle(c, statusCommandFunc)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// statusCommandFunc executes the "status" command.
|
||||
func statusCommandFunc(c *cli.Context, client *client.Client) error {
|
||||
var host, owner, repo, branch string
|
||||
var args = c.Args()
|
||||
|
||||
if len(args) != 0 {
|
||||
host, owner, repo = parseRepo(args[0])
|
||||
}
|
||||
|
||||
if c.IsSet("branch") {
|
||||
branch = c.String("branch")
|
||||
} else {
|
||||
branch = "master"
|
||||
}
|
||||
|
||||
builds, err := client.Commits.ListBranch(host, owner, repo, branch)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if len(builds) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var build = builds[len(builds)-1]
|
||||
fmt.Printf("%s\t%s\t%s\t%s\t%v", build.Status, build.ShaShort(), build.Timestamp, build.Author, build.Message)
|
||||
return nil
|
||||
}
|
101
cli/util.go
Normal file
101
cli/util.go
Normal file
@@ -0,0 +1,101 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func parseRepo(str string) (host, owner, repo string) {
|
||||
var parts = strings.Split(str, "/")
|
||||
if len(parts) != 3 {
|
||||
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
|
||||
// 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)
|
||||
}
|
32
cli/whoami.go
Normal file
32
cli/whoami.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/drone/drone/client"
|
||||
)
|
||||
|
||||
// NewWhoamiCommand returns the CLI command for "whoami".
|
||||
func NewWhoamiCommand() cli.Command {
|
||||
return cli.Command{
|
||||
Name: "whoami",
|
||||
Usage: "outputs the current user",
|
||||
Flags: []cli.Flag{},
|
||||
Action: func(c *cli.Context) {
|
||||
handle(c, whoamiCommandFunc)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// whoamiCommandFunc communicates with the server and echoes
|
||||
// the currently authenticated user.
|
||||
func whoamiCommandFunc(c *cli.Context, client *client.Client) error {
|
||||
user, err := client.Users.GetCurrent()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println(user.Login)
|
||||
return nil
|
||||
}
|
Reference in New Issue
Block a user