forked from vieter-v/vieter
				
			refactor: separated GitRepo types into own module
feat: added more query params for GitRepo APIhash-on-upload
							parent
							
								
									5e81dadce3
								
							
						
					
					
						commit
						6bd5b7cb48
					
				|  | @ -7,6 +7,7 @@ import os | |||
| import db | ||||
| import strings | ||||
| import util | ||||
| import models { GitRepo } | ||||
| 
 | ||||
| const ( | ||||
| 	container_build_dir = '/build' | ||||
|  | @ -93,7 +94,7 @@ pub: | |||
| // build_repo builds, packages & publishes a given Arch package based on the | ||||
| // provided GitRepo. The base image ID should be of an image previously created | ||||
| // by create_build_image. It returns the logs of the container. | ||||
| pub fn build_repo(address string, api_key string, base_image_id string, repo &db.GitRepo) ?BuildResult { | ||||
| pub fn build_repo(address string, api_key string, base_image_id string, repo &GitRepo) ?BuildResult { | ||||
| 	mut dd := docker.new_conn()? | ||||
| 
 | ||||
| 	defer { | ||||
|  |  | |||
|  | @ -29,8 +29,11 @@ fn (c &Client) send_request_raw(method Method, url string, params map[string]str | |||
| 
 | ||||
| 		// Escape each query param | ||||
| 		for k, v in params { | ||||
| 			// An empty parameter should be the same as not providing it at all | ||||
| 			if v != '' { | ||||
| 				params_escaped[k] = urllib.query_escape(v) | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		params_str := params_escaped.keys().map('$it=${params[it]}').join('&') | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,13 +1,12 @@ | |||
| module client | ||||
| 
 | ||||
| import db { GitRepo, GitRepoFilter } | ||||
| import models { GitRepo, GitRepoFilter } | ||||
| import net.http { Method } | ||||
| import response { Response } | ||||
| import util | ||||
| 
 | ||||
| // get_git_repos returns the current list of repos. | ||||
| pub fn (c &Client) get_git_repos(filter GitRepoFilter) ?[]GitRepo { | ||||
| 	params := util.struct_to_map(filter) | ||||
| 	params := models.params_from(filter) | ||||
| 	data := c.send_request<[]GitRepo>(Method.get, '/api/repos', params)? | ||||
| 
 | ||||
| 	return data.data | ||||
|  |  | |||
|  | @ -5,7 +5,7 @@ import env | |||
| import cron.expression { parse_expression } | ||||
| import client | ||||
| import console | ||||
| import db { GitRepoFilter } | ||||
| import models { GitRepoFilter } | ||||
| 
 | ||||
| struct Config { | ||||
| 	address    string [required] | ||||
|  | @ -50,21 +50,21 @@ pub fn cmd() cli.Command { | |||
| 
 | ||||
| 					mut filter := GitRepoFilter{} | ||||
| 
 | ||||
| 					if limit := cmd.flags.get_int('limit') { | ||||
| 						println('limit = $limit') | ||||
| 					limit := cmd.flags.get_int('limit')? | ||||
| 					if limit != 0 { | ||||
| 						filter.limit = u64(limit) | ||||
| 					} | ||||
| 
 | ||||
| 					if offset := cmd.flags.get_int('offset') { | ||||
| 						filter.limit = u64(offset) | ||||
| 					offset := cmd.flags.get_int('offset')? | ||||
| 					if offset != 0 { | ||||
| 						filter.offset = u64(offset) | ||||
| 					} | ||||
| 
 | ||||
| 					if repo := cmd.flags.get_string('repo') { | ||||
| 					repo := cmd.flags.get_string('repo')? | ||||
| 					if repo != '' { | ||||
| 						filter.repo = repo | ||||
| 					} | ||||
| 
 | ||||
| 					dump(filter) | ||||
| 
 | ||||
| 					list(conf, filter)? | ||||
| 				} | ||||
| 			}, | ||||
|  |  | |||
|  | @ -10,6 +10,7 @@ import docker | |||
| import db | ||||
| import os | ||||
| import client | ||||
| import models { GitRepo } | ||||
| 
 | ||||
| const ( | ||||
| 	// How many seconds to wait before retrying to update API if failed | ||||
|  | @ -20,7 +21,7 @@ const ( | |||
| 
 | ||||
| struct ScheduledBuild { | ||||
| pub: | ||||
| 	repo      db.GitRepo | ||||
| 	repo      GitRepo | ||||
| 	timestamp time.Time | ||||
| } | ||||
| 
 | ||||
|  | @ -38,7 +39,7 @@ mut: | |||
| 	api_update_frequency    int | ||||
| 	image_rebuild_frequency int | ||||
| 	// Repos currently loaded from API. | ||||
| 	repos []db.GitRepo | ||||
| 	repos []GitRepo | ||||
| 	// At what point to update the list of repositories. | ||||
| 	api_update_timestamp  time.Time | ||||
| 	image_build_timestamp time.Time | ||||
|  | @ -149,7 +150,7 @@ pub fn (mut d Daemon) run() { | |||
| } | ||||
| 
 | ||||
| // schedule_build adds the next occurence of the given repo build to the queue. | ||||
| fn (mut d Daemon) schedule_build(repo db.GitRepo) { | ||||
| fn (mut d Daemon) schedule_build(repo GitRepo) { | ||||
| 	ce := if repo.schedule != '' { | ||||
| 		parse_expression(repo.schedule) or { | ||||
| 			// TODO This shouldn't return an error if the expression is empty. | ||||
|  |  | |||
|  | @ -1,6 +1,7 @@ | |||
| module db | ||||
| 
 | ||||
| import sqlite | ||||
| import models | ||||
| 
 | ||||
| struct VieterDb { | ||||
| 	conn sqlite.DB | ||||
|  |  | |||
|  | @ -1,26 +0,0 @@ | |||
| module db | ||||
| 
 | ||||
| [params] | ||||
| pub struct GitRepoFilter { | ||||
| pub mut: | ||||
| 	limit  u64 = 25 | ||||
| 	offset u64 | ||||
| 	repo   string | ||||
| } | ||||
| 
 | ||||
| pub fn filter_from_params<T>(params map[string]string) ?T { | ||||
| 	mut o := GitRepoFilter{} | ||||
| 
 | ||||
| 	$for field in T.fields { | ||||
| 		if field.name in params { | ||||
| 			val := params[field.name] | ||||
| 
 | ||||
| 			$if field.typ is string { | ||||
| 				o.$(field.name) = val | ||||
| 			} $else $if field.typ is u64 { | ||||
| 				o.$(field.name) = val.u64() | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return o | ||||
| } | ||||
							
								
								
									
										77
									
								
								src/db/git.v
								
								
								
								
							
							
						
						
									
										77
									
								
								src/db/git.v
								
								
								
								
							|  | @ -1,84 +1,9 @@ | |||
| module db | ||||
| 
 | ||||
| pub struct GitRepoArch { | ||||
| pub: | ||||
| 	id      int    [primary; sql: serial] | ||||
| 	repo_id int    [nonull] | ||||
| 	value   string [nonull] | ||||
| } | ||||
| 
 | ||||
| // str returns a string representation. | ||||
| pub fn (gra &GitRepoArch) str() string { | ||||
| 	return gra.value | ||||
| } | ||||
| 
 | ||||
| pub struct GitRepo { | ||||
| pub mut: | ||||
| 	id int [optional; primary; sql: serial] | ||||
| 	// URL of the Git repository | ||||
| 	url string [nonull] | ||||
| 	// Branch of the Git repository to use | ||||
| 	branch string [nonull] | ||||
| 	// Which repo the builder should publish packages to | ||||
| 	repo string [nonull] | ||||
| 	// Cron schedule describing how frequently to build the repo. | ||||
| 	schedule string [optional] | ||||
| 	// On which architectures the package is allowed to be built. In reality, | ||||
| 	// this controls which builders will periodically build the image. | ||||
| 	arch []GitRepoArch [fkey: 'repo_id'] | ||||
| } | ||||
| 
 | ||||
| // str returns a string representation. | ||||
| pub fn (gr &GitRepo) str() string { | ||||
| 	mut parts := [ | ||||
| 		'id: $gr.id', | ||||
| 		'url: $gr.url', | ||||
| 		'branch: $gr.branch', | ||||
| 		'repo: $gr.repo', | ||||
| 		'schedule: $gr.schedule', | ||||
| 		'arch: ${gr.arch.map(it.value).join(', ')}', | ||||
| 	] | ||||
| 	str := parts.join('\n') | ||||
| 
 | ||||
| 	return str | ||||
| } | ||||
| 
 | ||||
| // patch_from_params patches a GitRepo from a map[string]string, usually | ||||
| // provided from a web.App's params | ||||
| pub fn (mut r GitRepo) patch_from_params(params map[string]string) { | ||||
| 	$for field in GitRepo.fields { | ||||
| 		if field.name in params { | ||||
| 			$if field.typ is string { | ||||
| 				r.$(field.name) = params[field.name] | ||||
| 				// This specific type check is needed for the compiler to ensure | ||||
| 				// our types are correct | ||||
| 			} $else $if field.typ is []GitRepoArch { | ||||
| 				r.$(field.name) = params[field.name].split(',').map(GitRepoArch{ value: it }) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // git_repo_from_params creates a GitRepo from a map[string]string, usually | ||||
| // provided from a web.App's params | ||||
| pub fn git_repo_from_params(params map[string]string) ?GitRepo { | ||||
| 	mut repo := GitRepo{} | ||||
| 
 | ||||
| 	// If we're creating a new GitRepo, we want all fields to be present before | ||||
| 	// "patching". | ||||
| 	$for field in GitRepo.fields { | ||||
| 		if field.name !in params && !field.attrs.contains('optional') { | ||||
| 			return error('Missing parameter: ${field.name}.') | ||||
| 		} | ||||
| 	} | ||||
| 	repo.patch_from_params(params) | ||||
| 
 | ||||
| 	return repo | ||||
| } | ||||
| import models { GitRepo, GitRepoArch, GitRepoFilter } | ||||
| 
 | ||||
| // get_git_repos returns all GitRepo's in the database. | ||||
| pub fn (db &VieterDb) get_git_repos(filter GitRepoFilter) []GitRepo { | ||||
| 	println(filter) | ||||
| 	// This seems to currently be blocked by a bug in the ORM, I'll have to ask | ||||
| 	// around. | ||||
| 	if filter.repo != '' { | ||||
|  |  | |||
|  | @ -0,0 +1,52 @@ | |||
| module models | ||||
| 
 | ||||
| pub struct GitRepoArch { | ||||
| pub: | ||||
| 	id      int    [primary; sql: serial] | ||||
| 	repo_id int    [nonull] | ||||
| 	value   string [nonull] | ||||
| } | ||||
| 
 | ||||
| // str returns a string representation. | ||||
| pub fn (gra &GitRepoArch) str() string { | ||||
| 	return gra.value | ||||
| } | ||||
| 
 | ||||
| pub struct GitRepo { | ||||
| pub mut: | ||||
| 	id int [primary; sql: serial] | ||||
| 	// URL of the Git repository | ||||
| 	url string [nonull] | ||||
| 	// Branch of the Git repository to use | ||||
| 	branch string [nonull] | ||||
| 	// Which repo the builder should publish packages to | ||||
| 	repo string [nonull] | ||||
| 	// Cron schedule describing how frequently to build the repo. | ||||
| 	schedule string | ||||
| 	// On which architectures the package is allowed to be built. In reality, | ||||
| 	// this controls which builders will periodically build the image. | ||||
| 	arch []GitRepoArch [fkey: 'repo_id'] | ||||
| } | ||||
| 
 | ||||
| // str returns a string representation. | ||||
| pub fn (gr &GitRepo) str() string { | ||||
| 	mut parts := [ | ||||
| 		'id: $gr.id', | ||||
| 		'url: $gr.url', | ||||
| 		'branch: $gr.branch', | ||||
| 		'repo: $gr.repo', | ||||
| 		'schedule: $gr.schedule', | ||||
| 		'arch: ${gr.arch.map(it.value).join(', ')}', | ||||
| 	] | ||||
| 	str := parts.join('\n') | ||||
| 
 | ||||
| 	return str | ||||
| } | ||||
| 
 | ||||
| [params] | ||||
| pub struct GitRepoFilter { | ||||
| pub mut: | ||||
| 	limit  u64 = 25 | ||||
| 	offset u64 | ||||
| 	repo   string | ||||
| } | ||||
|  | @ -0,0 +1,36 @@ | |||
| module models | ||||
| 
 | ||||
| pub fn from_params<T>(params map[string]string) ?T { | ||||
| 	mut o := T{} | ||||
| 
 | ||||
| 	patch_from_params<T>(mut o, params)? | ||||
| 
 | ||||
| 	return o | ||||
| } | ||||
| 
 | ||||
| pub fn patch_from_params<T>(mut o T, params map[string]string) ? { | ||||
| 	$for field in T.fields { | ||||
| 		if field.name in params && params[field.name] != '' { | ||||
| 			$if field.typ is string { | ||||
| 				o.$(field.name) = params[field.name] | ||||
| 			} $else $if field.typ is int { | ||||
| 				o.$(field.name) = params[field.name].int() | ||||
| 			} $else $if field.typ is u64 { | ||||
| 				o.$(field.name) = params[field.name].u64() | ||||
| 			} $else $if field.typ is []GitRepoArch { | ||||
| 				o.$(field.name) = params[field.name].split(',').map(GitRepoArch{ value: it }) | ||||
| 			} | ||||
| 		} else if field.attrs.contains('nonull') { | ||||
| 			return error('Missing parameter: ${field.name}.') | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| pub fn params_from<T>(o &T) map[string]string { | ||||
| 	mut out := map[string]string{} | ||||
| 
 | ||||
| 	$for field in T.fields { | ||||
| 		out[field.name] = o.$(field.name).str() | ||||
| 	} | ||||
| 	return out | ||||
| } | ||||
|  | @ -4,6 +4,7 @@ import web | |||
| import net.http | ||||
| import response { new_data_response, new_response } | ||||
| import db | ||||
| import models { GitRepoArch } | ||||
| 
 | ||||
| // get_repos returns the current list of repos. | ||||
| ['/api/repos'; get] | ||||
|  | @ -12,7 +13,7 @@ fn (mut app App) get_repos() web.Result { | |||
| 		return app.json(http.Status.unauthorized, new_response('Unauthorized.')) | ||||
| 	} | ||||
| 
 | ||||
| 	filter := db.filter_from_params<db.GitRepoFilter>(app.query) or { | ||||
| 	filter := models.from_params<GitRepoFilter>(app.query) or { | ||||
| 		return app.json(http.Status.bad_request, new_response('Invalid query parameters.')) | ||||
| 	} | ||||
| 	repos := app.db.get_git_repos(filter) | ||||
|  | @ -47,7 +48,7 @@ fn (mut app App) post_repo() web.Result { | |||
| 		params['arch'] = app.conf.default_arch | ||||
| 	} | ||||
| 
 | ||||
| 	new_repo := db.git_repo_from_params(params) or { | ||||
| 	new_repo := models.from_params<GitRepo>(params) or { | ||||
| 		return app.json(http.Status.bad_request, new_response(err.msg())) | ||||
| 	} | ||||
| 
 | ||||
|  | @ -78,7 +79,7 @@ fn (mut app App) patch_repo(id int) web.Result { | |||
| 	app.db.update_git_repo(id, app.query) | ||||
| 
 | ||||
| 	if 'arch' in app.query { | ||||
| 		arch_objs := app.query['arch'].split(',').map(db.GitRepoArch{ value: it }) | ||||
| 		arch_objs := app.query['arch'].split(',').map(GitRepoArch{ value: it }) | ||||
| 
 | ||||
| 		app.db.update_git_repo_archs(id, arch_objs) | ||||
| 	} | ||||
|  |  | |||
|  | @ -71,6 +71,5 @@ pub fn struct_to_map<T>(o T) map[string]string { | |||
| 	$for field in T.fields { | ||||
| 		m[field.name] = o.$(field.name).str() | ||||
| 	} | ||||
| 
 | ||||
| 	return m | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue