From 6ae9ae7f84342ff72bd9d528b7027839151f8fb2 Mon Sep 17 00:00:00 2001 From: Ole Herman Schumacher Elgesem Date: Tue, 15 Jul 2025 23:01:35 +0200 Subject: [PATCH 1/5] GH Actions: Added build all test from build-index repo This test might run into problems like being too slow, or running out of API quotas / rate limiting. We might disable it in the future, or merge it into the other similar test, at 'tests/shell/validate.sh'. However, for now, it is useful, especially as I'm debugging why this fails in the other repo. Signed-off-by: Ole Herman Schumacher Elgesem --- .github/workflows/add_validate_build_all.sh | 60 +++++++++++++++++++ .github/workflows/add_validate_build_all.yaml | 32 ++++++++++ 2 files changed, 92 insertions(+) create mode 100644 .github/workflows/add_validate_build_all.sh create mode 100644 .github/workflows/add_validate_build_all.yaml diff --git a/.github/workflows/add_validate_build_all.sh b/.github/workflows/add_validate_build_all.sh new file mode 100644 index 00000000..3e996773 --- /dev/null +++ b/.github/workflows/add_validate_build_all.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env + +# Requires / expects cfbs to already be installed +# Run from project root (will look for ./cfbs.json) +# in current working directory + +set -e +set -x + +rm -rf ./tmp/ +mkdir -p ./tmp/ + +# This script is written to also work in for example cfengine/cfbs +# where we'd need to downooad cfbs.json. +if [ ! -f ./cfbs.json ] ; then + echo "No cfbs.json found in current working directory, downloading from GitHub" + curl -L https://raw.githubusercontent.com/cfengine/build-index/refs/heads/master/cfbs.json -o ./tmp/cfbs.json +else + cp ./cfbs.json ./tmp/cfbs.json +fi + +cd ./tmp/ + +# Move the index to another filename +mv cfbs.json index.json + +# Initialize cfbs project +cfbs --non-interactive --index ./index.json init --masterfiles=no + +# Add masterfiles +cfbs --non-interactive add masterfiles + +# Validate the minimal project +cfbs validate + +# Add all modules +cfbs search --index ./index.json | \ +awk '{print $1}' | \ +xargs -n1 cfbs --index ./index.json add + +# Validate all modules +cfbs validate + +# Build +cfbs build --ignore-versions-json + +# Status +cfbs status + +# Here we use root for everything to avoid permissions problems in policy that accesses files +# TODO: Enable later +#- name: Validate built policy +# run: | +# sudo pip3 install cfbs +# wget https://s3.amazonaws.com/cfengine.packages/quick-install-cfengine-enterprise.sh && sudo bash ./quick-install-cfengine-enterprise.sh agent +# sudo cfbs install +# # fake a bootstrap, lib-fim module expects stdlib to be in inputs with $(sys.libdir) +# sudo cp -r /var/cfengine/masterfiles/lib /var/cfengine/inputs +# sudo cf-promises -f /var/cfengine/masterfiles/promises.cf +# sudo cf-promises -vf /var/cfengine/masterfiles/update.cf diff --git a/.github/workflows/add_validate_build_all.yaml b/.github/workflows/add_validate_build_all.yaml new file mode 100644 index 00000000..d0773d2e --- /dev/null +++ b/.github/workflows/add_validate_build_all.yaml @@ -0,0 +1,32 @@ +name: Add, validate, and build all modules + +# Controls when the workflow will run +on: + # Triggers the workflow on master every night at 3:15 am + schedule: + - cron: "15 3 * * *" + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +permissions: + contents: read + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + # This workflow contains a single job called "build" + build: + # The type of runner that the job will run on + runs-on: ubuntu-latest + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v2 + + - name: Install cfbs with pip + run: pip3 install cfbs + + # Downloading cfbs.json is needed to run this action in another repo, like cfengine/cfbs: + - name: Run test script + run: bash .github/workflows/add_validate_build_all.sh From 3223d0252677f89ad73c1506f4e6625a806f1153 Mon Sep 17 00:00:00 2001 From: Ole Herman Schumacher Elgesem Date: Tue, 15 Jul 2025 23:16:01 +0200 Subject: [PATCH 2/5] Fixed repeated warnings in cfbs validate while returning 0 (success) When we use warn_about_unused_keys from _validate_config() we really want it to raise exceptions, like the rest of the valiation code. validate_config() will handle the exception, and the code calling it will determine how strict to be when it comes to the result. (cfbs validate should be very strict, cfbs build is intentionally not strict for backwards compatibility, other commands are somewhere in between). This fixes an issue seen in the build index tests, where these warnings are printed many times by cfbs validate, because the "index" field is not recognized, and cfbs validate still exits with 0 (success). Further fixes are needed for other commands and for making cfbs validate recognize the "index" field, this is just the first step. Signed-off-by: Ole Herman Schumacher Elgesem --- cfbs/cfbs_json.py | 16 +++++++++++----- cfbs/validate.py | 4 +++- tests/test_validate_mock_index.py | 2 +- tests/test_validate_mock_input.py | 2 +- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/cfbs/cfbs_json.py b/cfbs/cfbs_json.py index 4ea011fc..5fd0df2c 100644 --- a/cfbs/cfbs_json.py +++ b/cfbs/cfbs_json.py @@ -4,7 +4,7 @@ from cfbs.index import Index from cfbs.pretty import pretty, TOP_LEVEL_KEYS, MODULE_KEYS -from cfbs.utils import read_json, CFBSExitError +from cfbs.utils import CFBSValidationError, read_json, CFBSExitError def _construct_provided_module(name, data, url, commit, added_by="cfbs add"): @@ -81,12 +81,12 @@ def _find_all_module_objects(self): modules += data["build"] return modules - def warn_about_unknown_keys(self): + def warn_about_unknown_keys(self, raise_exceptions=False): """Basic validation to warn the user when a cfbs.json has unknown keys. Unknown keys are typically due to typos, or an outdated version of cfbs. This basic type of - validation only produces warnings (we want cfbs to still work), + validation only produces warnings (we want cfbs build to still work), and is run for various cfbs commands, not just cfbs build / validate. For the more complete validation, see validate.py. """ @@ -97,20 +97,26 @@ def warn_about_unknown_keys(self): for key in data: if key not in TOP_LEVEL_KEYS: - log.warning( + msg = ( 'The top level key "%s" is not known to this version of cfbs.\n' + "Is it a typo? If not, try upgrading cfbs:\n" + "pip3 install --upgrade cfbs" ) + if raise_exceptions: + raise CFBSValidationError(msg) + log.warning(msg) for module in self._find_all_module_objects(): for key in module: if key not in MODULE_KEYS: - log.warning( + msg = ( 'The module level key "%s" is not known to this version of cfbs.\n' % key + "Is it a typo? If not, try upgrading cfbs:\n" + "pip3 install --upgrade cfbs" ) + if raise_exceptions: + raise CFBSValidationError(msg) + log.warning(msg) def _get_all_module_names(self, search_in=("build", "provides", "index")): modules = [] diff --git a/cfbs/validate.py b/cfbs/validate.py index c9e6678a..28f1694c 100644 --- a/cfbs/validate.py +++ b/cfbs/validate.py @@ -195,7 +195,9 @@ def validate_module_name_content(name): def _validate_config(config, empty_build_list_ok=False): # First validate the config i.e. the user's cfbs.json - config.warn_about_unknown_keys() + # Here we can raise exceptions, that's what the rest of + # the function does, and they are caught by validate_config() + config.warn_about_unknown_keys(raise_exceptions=True) _validate_top_level_keys(config) raw_data = config.raw_data diff --git a/tests/test_validate_mock_index.py b/tests/test_validate_mock_index.py index ae8aeedf..85ce92ad 100644 --- a/tests/test_validate_mock_index.py +++ b/tests/test_validate_mock_index.py @@ -12,7 +12,7 @@ class MockConfig(OrderedDict): def raw_data(self): return deepcopy(self) - def warn_about_unknown_keys(self): + def warn_about_unknown_keys(self, raise_exceptions=False): pass diff --git a/tests/test_validate_mock_input.py b/tests/test_validate_mock_input.py index 60cb0980..58c7d0cf 100644 --- a/tests/test_validate_mock_input.py +++ b/tests/test_validate_mock_input.py @@ -12,7 +12,7 @@ class MockConfig(OrderedDict): def raw_data(self): return deepcopy(self) - def warn_about_unknown_keys(self): + def warn_about_unknown_keys(self, raise_exceptions=False): pass From d78e2969ffc817c8feda36d588180d0bd3e00ae9 Mon Sep 17 00:00:00 2001 From: Ole Herman Schumacher Elgesem Date: Tue, 15 Jul 2025 23:22:36 +0200 Subject: [PATCH 3/5] Prevented spammy log messages about unknown keys in some commands When we are not using exceptions, avoid printing the same warning again and again. This fix is only for the places where we don't use the exceptions, for example, it has no effect on cfbs validate. Signed-off-by: Ole Herman Schumacher Elgesem --- cfbs/cfbs_json.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cfbs/cfbs_json.py b/cfbs/cfbs_json.py index 5fd0df2c..26f32e14 100644 --- a/cfbs/cfbs_json.py +++ b/cfbs/cfbs_json.py @@ -105,8 +105,11 @@ def warn_about_unknown_keys(self, raise_exceptions=False): if raise_exceptions: raise CFBSValidationError(msg) log.warning(msg) + already_printed = [] for module in self._find_all_module_objects(): for key in module: + if key in already_printed: + continue if key not in MODULE_KEYS: msg = ( 'The module level key "%s" is not known to this version of cfbs.\n' @@ -117,6 +120,7 @@ def warn_about_unknown_keys(self, raise_exceptions=False): if raise_exceptions: raise CFBSValidationError(msg) log.warning(msg) + already_printed.append(key) def _get_all_module_names(self, search_in=("build", "provides", "index")): modules = [] From dac376f504600a9bf19f806006905aa6ffe75234 Mon Sep 17 00:00:00 2001 From: Ole Herman Schumacher Elgesem Date: Tue, 15 Jul 2025 23:27:22 +0200 Subject: [PATCH 4/5] Renamed _validate_config() to validate_config_with_exceptions() It will be useful to call this function directly, in many cases. Signed-off-by: Ole Herman Schumacher Elgesem --- cfbs/validate.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cfbs/validate.py b/cfbs/validate.py index 28f1694c..eb11be86 100644 --- a/cfbs/validate.py +++ b/cfbs/validate.py @@ -193,7 +193,7 @@ def validate_module_name_content(name): log.debug("Validated name of module %s" % name) -def _validate_config(config, empty_build_list_ok=False): +def validate_config_raise_exceptions(config, empty_build_list_ok=False): # First validate the config i.e. the user's cfbs.json # Here we can raise exceptions, that's what the rest of # the function does, and they are caught by validate_config() @@ -219,7 +219,7 @@ def _validate_config(config, empty_build_list_ok=False): def validate_config(config, empty_build_list_ok=False): """Returns `0` if there are no validation errors, and `1` otherwise.""" try: - _validate_config(config, empty_build_list_ok) + validate_config_raise_exceptions(config, empty_build_list_ok) return 0 except CFBSValidationError as e: print(e) From 823e04dc4d12fe7f311adc2881cc0212adc73812 Mon Sep 17 00:00:00 2001 From: Ole Herman Schumacher Elgesem Date: Tue, 15 Jul 2025 23:49:26 +0200 Subject: [PATCH 5/5] Fixed shell test 11 after recent changes in build index Signed-off-by: Ole Herman Schumacher Elgesem --- tests/shell/011_update.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/shell/011_update.sh b/tests/shell/011_update.sh index 5243a576..6bab18cd 100644 --- a/tests/shell/011_update.sh +++ b/tests/shell/011_update.sh @@ -43,7 +43,7 @@ cat cfbs.json | grep -F "version" | grep -F "." cat cfbs.json | grep -F "commit" cat cfbs.json | grep -F "subdirectory" | grep -F "libraries/python" cat cfbs.json | grep -F "added_by" | grep -F "promise-type-ansible" -cat cfbs.json | grep -F "steps" | grep -F "copy cfengine.py modules/promises/" +cat cfbs.json | grep -F "copy cfengine_module_library.py modules/promises/cfengine_module_library.py" cfbs status cfbs build