feat: queue one-time builds from CLI
ci/woodpecker/pr/docs Pipeline was successful
Details
ci/woodpecker/pr/lint Pipeline failed
Details
ci/woodpecker/pr/build Pipeline was successful
Details
ci/woodpecker/pr/man Pipeline was successful
Details
ci/woodpecker/pr/docker Pipeline was successful
Details
ci/woodpecker/pr/test Pipeline was successful
Details
ci/woodpecker/pr/docs Pipeline was successful
Details
ci/woodpecker/pr/lint Pipeline failed
Details
ci/woodpecker/pr/build Pipeline was successful
Details
ci/woodpecker/pr/man Pipeline was successful
Details
ci/woodpecker/pr/docker Pipeline was successful
Details
ci/woodpecker/pr/test Pipeline was successful
Details
parent
6a208dbe6c
commit
b3e26e5ffe
|
@ -7,7 +7,7 @@ import datatypes { MinHeap }
|
||||||
import util
|
import util
|
||||||
|
|
||||||
struct BuildJob {
|
struct BuildJob {
|
||||||
pub:
|
pub mut:
|
||||||
// Time at which this build job was created/queued
|
// Time at which this build job was created/queued
|
||||||
created time.Time
|
created time.Time
|
||||||
// Next timestamp from which point this job is allowed to be executed
|
// Next timestamp from which point this job is allowed to be executed
|
||||||
|
@ -64,6 +64,8 @@ pub struct InsertConfig {
|
||||||
target Target [required]
|
target Target [required]
|
||||||
arch string [required]
|
arch string [required]
|
||||||
single bool
|
single bool
|
||||||
|
force bool
|
||||||
|
now bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// insert a new target's job into the queue for the given architecture. This
|
// 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>{}
|
q.queues[input.arch] = MinHeap<BuildJob>{}
|
||||||
}
|
}
|
||||||
|
|
||||||
ce := if input.target.schedule != '' {
|
mut job := BuildJob{
|
||||||
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{
|
|
||||||
created: time.now()
|
created: time.now()
|
||||||
timestamp: timestamp
|
|
||||||
ce: ce
|
|
||||||
single: input.single
|
single: input.single
|
||||||
config: BuildConfig{
|
config: BuildConfig{
|
||||||
target_id: input.target.id
|
target_id: input.target.id
|
||||||
|
@ -98,9 +88,25 @@ pub fn (mut q BuildJobQueue) insert(input InsertConfig) ! {
|
||||||
repo: input.target.repo
|
repo: input.target.repo
|
||||||
// TODO make this configurable
|
// TODO make this configurable
|
||||||
base_image: q.default_base_image
|
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)
|
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() {
|
if job.timestamp < time.now() {
|
||||||
job = q.queues[arch].pop() or { break }
|
job = q.queues[arch].pop() or { break }
|
||||||
|
|
||||||
// TODO idem
|
if !job.single {
|
||||||
q.reschedule(job, arch) or {}
|
// TODO idem
|
||||||
|
q.reschedule(job, arch) or {}
|
||||||
|
}
|
||||||
|
|
||||||
out << job
|
out << job
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
module client
|
module client
|
||||||
|
|
||||||
import build { BuildConfig }
|
import build { BuildConfig }
|
||||||
|
import web.response { Response }
|
||||||
|
|
||||||
// poll_jobs requests a list of new build jobs from the server.
|
// poll_jobs requests a list of new build jobs from the server.
|
||||||
pub fn (c &Client) poll_jobs(arch string, max int) ![]BuildConfig {
|
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
|
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,39 @@ pub fn cmd() cli.Command {
|
||||||
description: 'Build the target without checking whether it needs to be renewed.'
|
description: 'Build the target without checking whether it needs to be renewed.'
|
||||||
flag: cli.FlagType.bool
|
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) ! {
|
execute: fn (cmd cli.Command) ! {
|
||||||
config_file := cmd.flags.get_string('config-file')!
|
config_file := cmd.flags.get_string('config-file')!
|
||||||
conf := vconf.load<Config>(prefix: 'VIETER_', default_path: 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 == '' {
|
||||||
|
println('When scheduling the build remotely, you have to specify an architecture.')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
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.'))
|
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 {
|
target := app.db.get_target(target_id) or {
|
||||||
return app.json(.bad_request, new_response('Unknown target id.'))
|
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)
|
return app.status(.internal_server_error)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue