From 44696fc11b200aa903641f852282f32a96de117b Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Wed, 15 Jun 2022 13:20:29 +0200 Subject: [PATCH 1/2] refactor: migrated env code to own external module --- README.md | 4 ++ src/console/git/git.v | 14 +++--- src/console/logs/logs.v | 8 ++-- src/cron/cli.v | 4 +- src/env/README.md | 7 --- src/env/env.v | 102 ---------------------------------------- src/server/cli.v | 4 +- src/v.mod | 5 ++ 8 files changed, 24 insertions(+), 124 deletions(-) delete mode 100644 src/env/README.md delete mode 100644 src/env/env.v diff --git a/README.md b/README.md index 892396a..31f262e 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,10 @@ Besides a V installer, Vieter also requires the following libraries to work: * openssl * sqlite3 +Vieter also depends on some external V modules which you can install using `cd +src && v install`. Make sure to keep these dependencies up to date using `v +update`. + ### Compiler Vieter compiles with the standard Vlang compiler. However, I do maintain a diff --git a/src/console/git/git.v b/src/console/git/git.v index e27c1c4..303909e 100644 --- a/src/console/git/git.v +++ b/src/console/git/git.v @@ -1,7 +1,7 @@ module git import cli -import env +import vieter.vconf import cron.expression { parse_expression } import client import console @@ -41,7 +41,7 @@ pub fn cmd() cli.Command { ] execute: fn (cmd cli.Command) ? { config_file := cmd.flags.get_string('config-file')? - conf := env.load(config_file)? + conf := vconf.load(default_path: config_file)? mut filter := GitRepoFilter{} @@ -70,7 +70,7 @@ pub fn cmd() cli.Command { description: 'Add a new repository.' execute: fn (cmd cli.Command) ? { config_file := cmd.flags.get_string('config-file')? - conf := env.load(config_file)? + conf := vconf.load(default_path: config_file)? add(conf, cmd.args[0], cmd.args[1], cmd.args[2])? } @@ -82,7 +82,7 @@ pub fn cmd() cli.Command { description: 'Remove a repository that matches the given ID prefix.' execute: fn (cmd cli.Command) ? { config_file := cmd.flags.get_string('config-file')? - conf := env.load(config_file)? + conf := vconf.load(default_path: config_file)? remove(conf, cmd.args[0])? } @@ -94,7 +94,7 @@ pub fn cmd() cli.Command { description: 'Show detailed information for the repo matching the ID prefix.' execute: fn (cmd cli.Command) ? { config_file := cmd.flags.get_string('config-file')? - conf := env.load(config_file)? + conf := vconf.load(default_path: config_file)? info(conf, cmd.args[0])? } @@ -133,7 +133,7 @@ pub fn cmd() cli.Command { ] execute: fn (cmd cli.Command) ? { config_file := cmd.flags.get_string('config-file')? - conf := env.load(config_file)? + conf := vconf.load(default_path: config_file)? found := cmd.flags.get_all_found() @@ -155,7 +155,7 @@ pub fn cmd() cli.Command { description: 'Build the repo with the given id & publish it.' execute: fn (cmd cli.Command) ? { config_file := cmd.flags.get_string('config-file')? - conf := env.load(config_file)? + conf := vconf.load(default_path: config_file)? build(conf, cmd.args[0].int())? } diff --git a/src/console/logs/logs.v b/src/console/logs/logs.v index cb6997f..d63e284 100644 --- a/src/console/logs/logs.v +++ b/src/console/logs/logs.v @@ -1,7 +1,7 @@ module logs import cli -import env +import vieter.vconf import client import console import time @@ -65,7 +65,7 @@ pub fn cmd() cli.Command { ] execute: fn (cmd cli.Command) ? { config_file := cmd.flags.get_string('config-file')? - conf := env.load(config_file)? + conf := vconf.load(default_path: config_file)? mut filter := BuildLogFilter{} @@ -143,7 +143,7 @@ pub fn cmd() cli.Command { description: 'Show all info for a specific build log.' execute: fn (cmd cli.Command) ? { config_file := cmd.flags.get_string('config-file')? - conf := env.load(config_file)? + conf := vconf.load(default_path: config_file)? id := cmd.args[0].int() info(conf, id)? @@ -156,7 +156,7 @@ pub fn cmd() cli.Command { description: 'Output the content of a build log to stdout.' execute: fn (cmd cli.Command) ? { config_file := cmd.flags.get_string('config-file')? - conf := env.load(config_file)? + conf := vconf.load(default_path: config_file)? id := cmd.args[0].int() content(conf, id)? diff --git a/src/cron/cli.v b/src/cron/cli.v index 9703c66..10a4bdd 100644 --- a/src/cron/cli.v +++ b/src/cron/cli.v @@ -1,7 +1,7 @@ module cron import cli -import env +import vieter.vconf struct Config { pub: @@ -24,7 +24,7 @@ pub fn cmd() cli.Command { description: 'Start the cron service that periodically runs builds.' execute: fn (cmd cli.Command) ? { config_file := cmd.flags.get_string('config-file')? - conf := env.load(config_file)? + conf := vconf.load(default_path: config_file)? cron(conf)? } diff --git a/src/env/README.md b/src/env/README.md deleted file mode 100644 index 135e8fa..0000000 --- a/src/env/README.md +++ /dev/null @@ -1,7 +0,0 @@ -This module provides a framework for parsing a configuration, defined as a -struct, from both a TOML configuration file & environment variables. Some -notable features are: - -* Overwrite values in config file using environment variables -* Allow default values in config struct -* Read environment variable value from file diff --git a/src/env/env.v b/src/env/env.v deleted file mode 100644 index 5ed1955..0000000 --- a/src/env/env.v +++ /dev/null @@ -1,102 +0,0 @@ -module env - -import os -import toml - -const ( - // The prefix that every environment variable should have - prefix = 'VIETER_' - // The suffix an environment variable in order for it to be loaded from a file - // instead - file_suffix = '_FILE' -) - -// get_env_var tries to read the contents of the given environment variable. It -// looks for either `${env.prefix}${field_name.to_upper()}` or -// `${env.prefix}${field_name.to_upper()}${env.file_suffix}`, returning the -// contents of the file instead if the latter. If both or neither exist, the -// function returns an error. -fn get_env_var(field_name string) ?string { - env_var_name := '$env.prefix$field_name.to_upper()' - env_file_name := '$env.prefix$field_name.to_upper()$env.file_suffix' - env_var := os.getenv(env_var_name) - env_file := os.getenv(env_file_name) - - // If both are missing, we return an empty string - if env_var == '' && env_file == '' { - return '' - } - - // If they're both set, we report a conflict - if env_var != '' && env_file != '' { - return error('Only one of $env_var_name or $env_file_name can be defined.') - } - - // If it's the env var itself, we return it. - // I'm pretty sure this also prevents variable ending in _FILE (e.g. - // VIETER_LOG_FILE) from being mistakingely read as an _FILE suffixed env - // var. - if env_var != '' { - return env_var - } - - // Otherwise, we process the file - return os.read_file(env_file) or { - error('Failed to read file defined in $env_file_name: ${err.msg()}.') - } -} - -// load attempts to create an object of type T from the given path to a toml -// file & environment variables. For each field, it will select either a value -// given from an environment variable, a value defined in the config file or a -// configured default if present, in that order. -pub fn load(path string) ?T { - mut res := T{} - - if os.exists(path) { - // We don't use reflect here because reflect also sets any fields not - // in the toml back to their zero value, which we don't want - doc := toml.parse_file(path)? - - $for field in T.fields { - s := doc.value(field.name) - - if s !is toml.Null { - $if field.typ is string { - res.$(field.name) = s.string() - } $else $if field.typ is int { - res.$(field.name) = s.int() - } - } - } - } - - $for field in T.fields { - env_value := get_env_var(field.name)? - - // The value of an env var will always take precedence over the toml - // file. - if env_value != '' { - $if field.typ is string { - res.$(field.name) = env_value - } $else $if field.typ is int { - res.$(field.name) = env_value.int() - } - } - - // Now, we check whether a value is present. If there isn't, that means - // it isn't in the config file, nor is there a default or an env var. - mut has_value := false - - $if field.typ is string { - has_value = res.$(field.name) != '' - } $else $if field.typ is int { - has_value = res.$(field.name) != 0 - } - - if !has_value { - return error("Missing config variable '$field.name' with no provided default. Either add it to the config file or provide it using an environment variable.") - } - } - return res -} diff --git a/src/server/cli.v b/src/server/cli.v index 556efcf..cf0306c 100644 --- a/src/server/cli.v +++ b/src/server/cli.v @@ -1,7 +1,7 @@ module server import cli -import env +import vieter.vconf struct Config { pub: @@ -19,7 +19,7 @@ pub fn cmd() cli.Command { description: 'Start the Vieter server.' execute: fn (cmd cli.Command) ? { config_file := cmd.flags.get_string('config-file')? - conf := env.load(config_file)? + conf := vconf.load(default_path: config_file)? server(conf)? } diff --git a/src/v.mod b/src/v.mod index e69de29..7f45917 100644 --- a/src/v.mod +++ b/src/v.mod @@ -0,0 +1,5 @@ +Module { + dependencies: [ + 'https://git.rustybever.be/vieter/vconf' + ] +} From 592241c743d4f7f7c9ec065f422a3ccf5e2068d4 Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Wed, 15 Jun 2022 17:47:12 +0200 Subject: [PATCH 2/2] chore: updated CI config & PKGBUILDs to new module split --- .woodpecker/.build.yml | 13 +++++++++++-- PKGBUILD | 8 ++++++++ PKGBUILD.dev | 8 ++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/.woodpecker/.build.yml b/.woodpecker/.build.yml index b0fd267..d073b6c 100644 --- a/.woodpecker/.build.yml +++ b/.woodpecker/.build.yml @@ -6,10 +6,19 @@ matrix: platform: ${PLATFORM} pipeline: - debug: + install-modules: image: 'chewingbever/vlang:latest' pull: true commands: + - export VMODULES=$PWD/.vmodules + - 'cd src && v install' + when: + event: [pull_request] + + debug: + image: 'chewingbever/vlang:latest' + commands: + - export VMODULES=$PWD/.vmodules - make when: event: [pull_request] @@ -18,10 +27,10 @@ pipeline: prod: image: 'chewingbever/vlang:latest' - pull: true environment: - LDFLAGS=-lz -lbz2 -llzma -lexpat -lzstd -llz4 -lsqlite3 -static commands: + - export VMODULES=$PWD/.vmodules # Apparently this -D is *very* important - CFLAGS='-DGC_THREADS=1' make prod # Make sure the binary is actually statically built diff --git a/PKGBUILD b/PKGBUILD index 639ce95..33faec5 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -14,7 +14,15 @@ license=('AGPL3') source=("$pkgname::git+https://git.rustybever.be/vieter/vieter#tag=${pkgver//_/-}") md5sums=('SKIP') +prepare() { + export VMODULES="$srcdir/.vmodules" + + cd "$pkgname/src" && v install +} + build() { + export VMODULES="$srcdir/.vmodules" + cd "$pkgname" make prod diff --git a/PKGBUILD.dev b/PKGBUILD.dev index d25abb3..bff1459 100644 --- a/PKGBUILD.dev +++ b/PKGBUILD.dev @@ -22,7 +22,15 @@ pkgver() { git describe --long --tags | sed 's/^v//;s/\([^-]*-g\)/r\1/;s/-/./g' } +prepare() { + export VMODULES="$srcdir/.vmodules" + + cd "$pkgname/src" && v install +} + build() { + export VMODULES="$srcdir/.vmodules" + cd "$pkgname" make prod