forked from vieter-v/vieter
feat: queue one-time builds from CLI
parent
6a208dbe6c
commit
2cc3e8404e
|
@ -7,7 +7,7 @@ import datatypes { MinHeap }
|
|||
import util
|
||||
|
||||
struct BuildJob {
|
||||
pub:
|
||||
pub mut:
|
||||
// Time at which this build job was created/queued
|
||||
created time.Time
|
||||
// Next timestamp from which point this job is allowed to be executed
|
||||
|
@ -64,6 +64,8 @@ pub struct InsertConfig {
|
|||
target Target [required]
|
||||
arch string [required]
|
||||
single bool
|
||||
force bool
|
||||
now bool
|
||||
}
|
||||
|
||||
// insert a new target's job into the queue for the given architecture. This
|
||||
|
@ -75,20 +77,8 @@ pub fn (mut q BuildJobQueue) insert(input InsertConfig) ! {
|
|||
q.queues[input.arch] = MinHeap<BuildJob>{}
|
||||
}
|
||||
|
||||
ce := if input.target.schedule != '' {
|
||||
parse_expression(input.target.schedule) or {
|
||||
return error("Error while parsing cron expression '$input.target.schedule' (id $input.target.id): $err.msg()")
|
||||
}
|
||||
} else {
|
||||
q.default_schedule
|
||||
}
|
||||
|
||||
timestamp := ce.next_from_now()!
|
||||
|
||||
job := BuildJob{
|
||||
mut job := BuildJob{
|
||||
created: time.now()
|
||||
timestamp: timestamp
|
||||
ce: ce
|
||||
single: input.single
|
||||
config: BuildConfig{
|
||||
target_id: input.target.id
|
||||
|
@ -98,9 +88,25 @@ pub fn (mut q BuildJobQueue) insert(input InsertConfig) ! {
|
|||
repo: input.target.repo
|
||||
// TODO make this configurable
|
||||
base_image: q.default_base_image
|
||||
force: input.force
|
||||
}
|
||||
}
|
||||
|
||||
if !input.now {
|
||||
ce := if input.target.schedule != '' {
|
||||
parse_expression(input.target.schedule) or {
|
||||
return error("Error while parsing cron expression '$input.target.schedule' (id $input.target.id): $err.msg()")
|
||||
}
|
||||
} else {
|
||||
q.default_schedule
|
||||
}
|
||||
|
||||
job.timestamp = ce.next_from_now()!
|
||||
job.ce = ce
|
||||
} else {
|
||||
job.timestamp = time.now()
|
||||
}
|
||||
|
||||
q.queues[input.arch].insert(job)
|
||||
}
|
||||
}
|
||||
|
@ -198,8 +204,10 @@ pub fn (mut q BuildJobQueue) pop_n(arch string, n int) []BuildJob {
|
|||
if job.timestamp < time.now() {
|
||||
job = q.queues[arch].pop() or { break }
|
||||
|
||||
if !job.single {
|
||||
// TODO idem
|
||||
q.reschedule(job, arch) or {}
|
||||
}
|
||||
|
||||
out << job
|
||||
} else {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
module client
|
||||
|
||||
import build { BuildConfig }
|
||||
import web.response { Response }
|
||||
|
||||
// poll_jobs requests a list of new build jobs from the server.
|
||||
pub fn (c &Client) poll_jobs(arch string, max int) ![]BuildConfig {
|
||||
|
@ -11,3 +12,13 @@ pub fn (c &Client) poll_jobs(arch string, max int) ![]BuildConfig {
|
|||
|
||||
return data.data
|
||||
}
|
||||
|
||||
pub fn (c &Client) queue_job(target_id int, arch string, force bool) !Response<string> {
|
||||
data := c.send_request<string>(.post, '/api/v1/jobs/queue', {
|
||||
'target': target_id.str()
|
||||
'arch': arch
|
||||
'force': force.str()
|
||||
})!
|
||||
|
||||
return data
|
||||
}
|
||||
|
|
|
@ -188,12 +188,38 @@ pub fn cmd() cli.Command {
|
|||
description: 'Build the target without checking whether it needs to be renewed.'
|
||||
flag: cli.FlagType.bool
|
||||
},
|
||||
cli.Flag{
|
||||
name: 'remote'
|
||||
description: 'Schedule the build on the server instead of running it locally.'
|
||||
flag: cli.FlagType.bool
|
||||
},
|
||||
cli.Flag{
|
||||
name: 'arch'
|
||||
description: 'Architecture to schedule build for. Required when using -remote.'
|
||||
flag: cli.FlagType.string
|
||||
},
|
||||
]
|
||||
execute: fn (cmd cli.Command) ! {
|
||||
config_file := cmd.flags.get_string('config-file')!
|
||||
conf := vconf.load<Config>(prefix: 'VIETER_', default_path: config_file)!
|
||||
|
||||
build(conf, cmd.args[0].int(), cmd.flags.get_bool('force')!)!
|
||||
remote := cmd.flags.get_bool('remote')!
|
||||
force := cmd.flags.get_bool('force')!
|
||||
target_id := cmd.args[0].int()
|
||||
|
||||
if remote {
|
||||
arch := cmd.flags.get_string('arch')!
|
||||
|
||||
if arch == '' {
|
||||
return error('When scheduling the build remotely, you have to specify an architecture.')
|
||||
}
|
||||
|
||||
c := client.new(conf.address, conf.api_key)
|
||||
res := c.queue_job(target_id, arch, force)!
|
||||
println(res.message)
|
||||
} else {
|
||||
build(conf, target_id, force)!
|
||||
}
|
||||
}
|
||||
},
|
||||
]
|
||||
|
|
|
@ -30,11 +30,17 @@ fn (mut app App) v1_queue_job() web.Result {
|
|||
return app.json(.bad_request, new_response('Missing arch query arg.'))
|
||||
}
|
||||
|
||||
if arch == '' {
|
||||
app.json(.bad_request, new_response('Empty arch query arg.'))
|
||||
}
|
||||
|
||||
force := 'force' in app.query
|
||||
|
||||
target := app.db.get_target(target_id) or {
|
||||
return app.json(.bad_request, new_response('Unknown target id.'))
|
||||
}
|
||||
|
||||
app.job_queue.insert(target: target, arch: arch, single: true) or {
|
||||
app.job_queue.insert(target: target, arch: arch, single: true, now: true, force: force) or {
|
||||
return app.status(.internal_server_error)
|
||||
}
|
||||
|
Loading…
Reference in New Issue