Merge pull request #1628 from bradrydzewski/master

added query, endpoint, cmd to list builds in queue
This commit is contained in:
Brad Rydzewski 2016-05-10 22:26:49 -07:00
commit 540f95630e
12 changed files with 172 additions and 61 deletions

View file

@ -33,8 +33,8 @@ type Client interface {
// Repo returns a repository by name.
Repo(string, string) (*model.Repo, error)
// RepoList returns a list of all repositories to which
// the user has explicit access in the host system.
// RepoList returns a list of all repositories to which the user has explicit
// access in the host system.
RepoList() ([]*model.Repo, error)
// RepoPost activates a repository.
@ -58,29 +58,32 @@ type Client interface {
// Build returns a repository build by number.
Build(string, string, int) (*model.Build, error)
// BuildLast returns the latest repository build by branch.
// An empty branch will result in the default branch.
// BuildLast returns the latest repository build by branch. An empty branch
// will result in the default branch.
BuildLast(string, string, string) (*model.Build, error)
// BuildList returns a list of recent builds for the
// the specified repository.
BuildList(string, string) ([]*model.Build, error)
// BuildQueue returns a list of enqueued builds.
BuildQueue() ([]*model.Feed, error)
// BuildStart re-starts a stopped build.
BuildStart(string, string, int) (*model.Build, error)
// BuildStop stops the specified running job for given build.
BuildStop(string, string, int, int) error
// BuildFork re-starts a stopped build with a new build number,
// preserving the prior history.
// BuildFork re-starts a stopped build with a new build number, preserving
// the prior history.
BuildFork(string, string, int) (*model.Build, error)
// BuildLogs returns the build logs for the specified job.
BuildLogs(string, string, int, int) (io.ReadCloser, error)
// Deploy triggers a deployment for an existing build using the
// specified target environment.
// Deploy triggers a deployment for an existing build using the specified
// target environment.
Deploy(string, string, int, string) (*model.Build, error)
//

View file

@ -24,23 +24,24 @@ const (
pathStream = "%s/api/queue/stream/%d"
pathPush = "%s/api/queue/status/%d"
pathSelf = "%s/api/user"
pathFeed = "%s/api/user/feed"
pathRepos = "%s/api/user/repos"
pathRepo = "%s/api/repos/%s/%s"
pathEncrypt = "%s/api/repos/%s/%s/encrypt"
pathBuilds = "%s/api/repos/%s/%s/builds"
pathBuild = "%s/api/repos/%s/%s/builds/%v"
pathJob = "%s/api/repos/%s/%s/builds/%d/%d"
pathLog = "%s/api/repos/%s/%s/logs/%d/%d"
pathKey = "%s/api/repos/%s/%s/key"
pathSign = "%s/api/repos/%s/%s/sign"
pathSecrets = "%s/api/repos/%s/%s/secrets"
pathSecret = "%s/api/repos/%s/%s/secrets/%s"
pathNodes = "%s/api/nodes"
pathNode = "%s/api/nodes/%d"
pathUsers = "%s/api/users"
pathUser = "%s/api/users/%s"
pathSelf = "%s/api/user"
pathFeed = "%s/api/user/feed"
pathRepos = "%s/api/user/repos"
pathRepo = "%s/api/repos/%s/%s"
pathEncrypt = "%s/api/repos/%s/%s/encrypt"
pathBuilds = "%s/api/repos/%s/%s/builds"
pathBuild = "%s/api/repos/%s/%s/builds/%v"
pathJob = "%s/api/repos/%s/%s/builds/%d/%d"
pathLog = "%s/api/repos/%s/%s/logs/%d/%d"
pathKey = "%s/api/repos/%s/%s/key"
pathSign = "%s/api/repos/%s/%s/sign"
pathSecrets = "%s/api/repos/%s/%s/secrets"
pathSecret = "%s/api/repos/%s/%s/secrets/%s"
pathNodes = "%s/api/nodes"
pathNode = "%s/api/nodes/%d"
pathUsers = "%s/api/users"
pathUser = "%s/api/users/%s"
pathBuildQueue = "%s/api/builds"
)
type client struct {
@ -189,6 +190,14 @@ func (c *client) BuildList(owner, name string) ([]*model.Build, error) {
return out, err
}
// BuildQueue returns a list of enqueued builds.
func (c *client) BuildQueue() ([]*model.Feed, error) {
var out []*model.Feed
uri := fmt.Sprintf(pathBuildQueue, c.base)
err := c.get(uri, &out)
return out, err
}
// BuildStart re-starts a stopped build.
func (c *client) BuildStart(owner, name string, num int) (*model.Build, error) {
out := new(model.Build)

View file

@ -53,8 +53,8 @@ var AgentCmd = cli.Command{
Value: "amd64",
},
cli.StringFlag{
EnvVar: "DOCKER_STORAGE_DRIVER",
Name: "docker-storage-driver",
EnvVar: "DRONE_STORAGE_DRIVER",
Name: "drone-storage-driver",
Usage: "docker storage driver",
Value: "overlay",
},
@ -80,26 +80,6 @@ var AgentCmd = cli.Command{
Name: "debug",
Usage: "start the agent in debug mode",
},
cli.BoolFlag{
EnvVar: "DRONE_EXPERIMENTAL",
Name: "experimental",
Usage: "start the agent with experimental features",
},
cli.StringSliceFlag{
EnvVar: "DRONE_PLUGIN_NETRC",
Name: "netrc-plugin",
Usage: "plugins that receive the netrc file",
Value: &cli.StringSlice{
"git",
"git:*",
"hg",
"hg:*",
"plugins/hg",
"plugins/hg:*",
"plugins/git",
"plugins/git:*",
},
},
cli.StringSliceFlag{
EnvVar: "DRONE_PLUGIN_PRIVILEGED",
Name: "privileged",
@ -113,22 +93,16 @@ var AgentCmd = cli.Command{
"plugins/ecr:*",
},
},
cli.BoolFlag{
EnvVar: "DRONE_PLUGIN_PULL",
Name: "pull",
Usage: "always pull latest plugin images",
},
cli.StringFlag{
EnvVar: "DRONE_PLUGIN_NAMESPACE",
Name: "namespace",
Value: "plugins",
Usage: "default plugin image namespace",
},
cli.StringSliceFlag{
EnvVar: "DRONE_PLUGIN_WHITELIST",
Name: "whitelist",
Usage: "plugins that are permitted to run on the host",
Value: &cli.StringSlice{"plugins/*"},
cli.BoolFlag{
EnvVar: "DRONE_PLUGIN_PULL",
Name: "pull",
Usage: "always pull latest plugin images",
},
},
}
@ -168,10 +142,8 @@ func start(c *cli.Context) {
drone: client,
docker: docker,
config: config{
whitelist: c.StringSlice("whitelist"),
namespace: c.String("namespace"),
privileged: c.StringSlice("privileged"),
netrc: c.StringSlice("netrc-plugin"),
pull: c.Bool("pull"),
},
}

View file

@ -15,9 +15,7 @@ import (
type config struct {
platform string
namespace string
whitelist []string
privileged []string
netrc []string
pull bool
}

View file

@ -11,5 +11,6 @@ var buildCmd = cli.Command{
buildInfoCmd,
buildStopCmd,
buildStartCmd,
buildQueueCmd,
},
}

60
drone/build_queue.go Normal file
View file

@ -0,0 +1,60 @@
package main
import (
"log"
"os"
"text/template"
"github.com/codegangsta/cli"
)
var buildQueueCmd = cli.Command{
Name: "queue",
Usage: "show build queue",
Action: func(c *cli.Context) {
if err := buildQueue(c); err != nil {
log.Fatalln(err)
}
},
Flags: []cli.Flag{
cli.StringFlag{
Name: "format",
Usage: "format output",
Value: tmplBuildQueue,
},
},
}
func buildQueue(c *cli.Context) error {
client, err := newClient(c)
if err != nil {
return err
}
builds, err := client.BuildQueue()
if err != nil {
return err
}
tmpl, err := template.New("_").Parse(c.String("format") + "\n")
if err != nil {
return err
}
for _, build := range builds {
tmpl.Execute(os.Stdout, build)
}
return nil
}
// template for build list information
var tmplBuildQueue = "\x1b[33m{{ .FullName }} #{{ .Number }} \x1b[0m" + `
Status: {{ .Status }}
Event: {{ .Event }}
Commit: {{ .Commit }}
Branch: {{ .Branch }}
Ref: {{ .Ref }}
Author: {{ .Author }} {{ if .Email }}<{{.Email}}>{{ end }}
Message: {{ .Message }}
`

View file

@ -135,6 +135,16 @@ func Load(middleware ...gin.HandlerFunc) http.Handler {
auth.POST("/token", server.GetLoginToken)
}
builds := e.Group("/api/builds")
{
builds.Use(session.MustAdmin())
builds.GET("", server.GetBuildQueue)
}
// agents := e.Group("/api/agents") {
// builds.Use(session.MustAdmin, server.GetAgents)
// }
queue := e.Group("/api/queue")
{
queue.Use(session.AuthorizeAgent)

View file

@ -305,3 +305,12 @@ func PostBuild(c *gin.Context) {
})
}
}
func GetBuildQueue(c *gin.Context) {
out, err := store.GetBuildQueue(c)
if err != nil {
c.String(500, "Error getting build queue. %s", err)
return
}
c.JSON(200, out)
}

View file

@ -49,6 +49,12 @@ func (db *datastore) GetBuildList(repo *model.Repo) ([]*model.Build, error) {
return builds, err
}
func (db *datastore) GetBuildQueue() ([]*model.Feed, error) {
feed := []*model.Feed{}
err := meddler.QueryAll(db, &feed, buildQueueList)
return feed, err
}
func (db *datastore) CreateBuild(build *model.Build, jobs ...*model.Job) error {
var number int
db.QueryRow(rebind(buildNumberLast), build.RepoID).Scan(&number)
@ -135,3 +141,31 @@ SELECT MAX(build_number)
FROM builds
WHERE build_repo_id = ?
`
const buildQueueList = `
SELECT
repo_owner
,repo_name
,repo_full_name
,build_number
,build_event
,build_status
,build_created
,build_started
,build_finished
,build_commit
,build_branch
,build_ref
,build_refspec
,build_remote
,build_title
,build_message
,build_author
,build_email
,build_avatar
FROM
builds b
,repos r
WHERE b.build_repo_id = r.repo_id
AND b.build_status IN ('pending','running')
`

View file

@ -6,7 +6,11 @@ ALTER TABLE builds ADD COLUMN build_verified BOOLEAN;
UPDATE builds SET build_signed = false;
UPDATE builds SET build_verified = false;
CREATE INDEX ix_build_status_running ON builds (build_status)
WHERE build_status IN ('pending', 'running');
-- +migrate Down
ALTER TABLE builds DROP COLUMN build_signed;
ALTER TABLE builds DROP COLUMN build_verified;
DROP INDEX ix_build_status_running;

View file

@ -6,7 +6,11 @@ ALTER TABLE builds ADD COLUMN build_verified BOOLEAN;
UPDATE builds SET build_signed = 0;
UPDATE builds SET build_verified = 0;
CREATE INDEX ix_build_status_running ON builds (build_status)
WHERE build_status IN ('pending', 'running');
-- +migrate Down
ALTER TABLE builds DROP COLUMN build_signed;
ALTER TABLE builds DROP COLUMN build_verified;
DROP INDEX ix_build_status_running;

View file

@ -87,6 +87,9 @@ type Store interface {
// GetBuildList gets a list of builds for the repository
GetBuildList(*model.Repo) ([]*model.Build, error)
// GetBuildQueue gets a list of build in queue.
GetBuildQueue() ([]*model.Feed, error)
// CreateBuild creates a new build and jobs.
CreateBuild(*model.Build, ...*model.Job) error
@ -224,6 +227,10 @@ func GetBuildList(c context.Context, repo *model.Repo) ([]*model.Build, error) {
return FromContext(c).GetBuildList(repo)
}
func GetBuildQueue(c context.Context) ([]*model.Feed, error) {
return FromContext(c).GetBuildQueue()
}
func CreateBuild(c context.Context, build *model.Build, jobs ...*model.Job) error {
return FromContext(c).CreateBuild(build, jobs...)
}