module targets import cli import conf as vconf import cron import client { NewTarget } import console import models { TargetFilter } struct Config { address string [required] api_key string [required] base_image string = 'archlinux:base-devel' } // cmd returns the cli submodule that handles the targets API interaction pub fn cmd() cli.Command { return cli.Command{ name: 'targets' description: 'Interact with the targets API.' commands: [ cli.Command{ name: 'list' description: 'List the current targets.' flags: [ cli.Flag{ name: 'limit' abbrev: 'l' description: 'How many results to return.' flag: cli.FlagType.int }, cli.Flag{ name: 'offset' abbrev: 'o' description: 'Minimum index to return.' flag: cli.FlagType.int }, cli.Flag{ name: 'repo' description: 'Only return targets that publish to this repo.' flag: cli.FlagType.string }, cli.Flag{ name: 'query' abbrev: 'q' description: 'Search string to filter targets by.' flag: cli.FlagType.string }, cli.Flag{ name: 'arch' description: 'Only list targets that build for this arch.' flag: cli.FlagType.string }, ] execute: fn (cmd cli.Command) ! { config_file := cmd.flags.get_string('config-file')! conf := vconf.load(prefix: 'VIETER_', default_path: config_file)! mut filter := TargetFilter{} limit := cmd.flags.get_int('limit')! if limit != 0 { filter.limit = u64(limit) } offset := cmd.flags.get_int('offset')! if offset != 0 { filter.offset = u64(offset) } repo := cmd.flags.get_string('repo')! if repo != '' { filter.repo = repo } query := cmd.flags.get_string('query')! if query != '' { filter.query = query } arch := cmd.flags.get_string('arch')! if arch != '' { filter.arch = arch } raw := cmd.flags.get_bool('raw')! list(conf, filter, raw)! } }, cli.Command{ name: 'add' required_args: 2 usage: 'url repo' description: 'Add a new target with the given URL & target repo.' flags: [ cli.Flag{ name: 'kind' description: "Kind of target to add. Defaults to 'git' if not specified. One of 'git', 'url'." flag: cli.FlagType.string default_value: ['git'] }, cli.Flag{ name: 'branch' description: "Which branch to clone; only applies to kind 'git'." flag: cli.FlagType.string }, cli.Flag{ name: 'path' description: 'Subdirectory inside Git repository to use.' flag: cli.FlagType.string }, ] execute: fn (cmd cli.Command) ! { config_file := cmd.flags.get_string('config-file')! conf := vconf.load(prefix: 'VIETER_', default_path: config_file)! t := NewTarget{ kind: cmd.flags.get_string('kind')! url: cmd.args[0] repo: cmd.args[1] branch: cmd.flags.get_string('branch') or { '' } path: cmd.flags.get_string('path') or { '' } } raw := cmd.flags.get_bool('raw')! add(conf, t, raw)! } }, cli.Command{ name: 'remove' required_args: 1 usage: 'id' description: 'Remove a target that matches the given id.' execute: fn (cmd cli.Command) ! { config_file := cmd.flags.get_string('config-file')! conf := vconf.load(prefix: 'VIETER_', default_path: config_file)! remove(conf, cmd.args[0])! } }, cli.Command{ name: 'info' required_args: 1 usage: 'id' description: 'Show detailed information for the target matching the id.' execute: fn (cmd cli.Command) ! { config_file := cmd.flags.get_string('config-file')! conf := vconf.load(prefix: 'VIETER_', default_path: config_file)! info(conf, cmd.args[0])! } }, cli.Command{ name: 'edit' required_args: 1 usage: 'id' description: 'Edit the target that matches the given id.' flags: [ cli.Flag{ name: 'url' description: 'URL value. Meaning depends on kind of target.' flag: cli.FlagType.string }, cli.Flag{ name: 'branch' description: 'Branch of the Git repository.' flag: cli.FlagType.string }, cli.Flag{ name: 'repo' description: 'Repo to publish builds to.' flag: cli.FlagType.string }, cli.Flag{ name: 'arch' description: 'Comma-separated list of architectures to build on.' flag: cli.FlagType.string }, cli.Flag{ name: 'schedule' description: 'Cron schedule for repository.' flag: cli.FlagType.string }, cli.Flag{ name: 'kind' description: 'Kind of target.' flag: cli.FlagType.string }, cli.Flag{ name: 'path' description: 'Subdirectory inside Git repository to use.' flag: cli.FlagType.string }, ] execute: fn (cmd cli.Command) ! { config_file := cmd.flags.get_string('config-file')! conf := vconf.load(prefix: 'VIETER_', default_path: config_file)! found := cmd.flags.get_all_found() mut params := map[string]string{} for f in found { if f.name != 'config-file' { params[f.name] = f.get_string()! } } patch(conf, cmd.args[0], params)! } }, cli.Command{ name: 'build' required_args: 1 usage: 'id' description: 'Build the target with the given id & publish it.' flags: [ cli.Flag{ name: 'force' 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(prefix: 'VIETER_', default_path: config_file)! 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) c.queue_job(target_id, arch, force)! } else { build(conf, target_id, force)! } } }, ] } } // list prints out a list of all repositories. fn list(conf Config, filter TargetFilter, raw bool) ! { c := client.new(conf.address, conf.api_key) targets := c.get_targets(filter)! data := targets.map([it.id.str(), it.kind, it.url, it.repo]) if raw { println(console.tabbed_table(data)) } else { println(console.pretty_table(['id', 'kind', 'url', 'repo'], data)!) } } // add adds a new target to the server's list. fn add(conf Config, t &NewTarget, raw bool) ! { c := client.new(conf.address, conf.api_key) target_id := c.add_target(t)! if raw { println(target_id) } else { println('Target added with id $target_id') } } // remove removes a target from the server's list. fn remove(conf Config, id string) ! { c := client.new(conf.address, conf.api_key) c.remove_target(id.int())! } // patch patches a given target with the provided params. fn patch(conf Config, id string, params map[string]string) ! { // We check the cron expression first because it's useless to send an // invalid one to the server. if 'schedule' in params && params['schedule'] != '' { cron.parse_expression(params['schedule']) or { return error('Invalid cron expression: $err.msg()') } } c := client.new(conf.address, conf.api_key) c.patch_target(id.int(), params)! } // info shows detailed information for a given target. fn info(conf Config, id string) ! { c := client.new(conf.address, conf.api_key) target := c.get_target(id.int())! println(target) }