From daf655a0d5b9836b817d26a6bcf709c0f91ef7d0 Mon Sep 17 00:00:00 2001 From: Stephen Gallagher Date: Jan 10 2019 18:39:11 +0000 Subject: [PATCH 1/5] Run tests under docker. Gain control over what is installed on the test nodes. Also switch to having all tests run under either tests/common_tests.sh or tests/pr_tests.sh, which will handle PRs better that want to change the current tests. Signed-off-by: Stephen Gallagher --- diff --git a/.cico.pipeline b/.cico.pipeline index 60e6dd6..17182cc 100644 --- a/.cico.pipeline +++ b/.cico.pipeline @@ -1,28 +1,19 @@ -node('fedora27') { - - properties([ - parameters([ - string(defaultValue: "", description: "", name: "REPO"), - string(defaultValue: "", description: "", name: "BRANCH"), - ]) - ]) +pipeline { + parameters { + string(defaultValue: "", description: "", name: "REPO") + string(defaultValue: "", description: "", name: "BRANCH") + } - try { - deleteDir() - stage('Clone Test Suite') { - sh "git clone --single-branch --depth 1 https://pagure.io/releng/fedora-module-defaults.git" - } + agent { node { label 'fedora29' } } - stage('Run Test Suite') { - timeout(time: 6, unit: 'HOURS') { - sh 'cd fedora-module-defaults && sh ./run_tests.sh' + stages { + stage('Validate Content') { + agent { + dockerfile { label 'fedora29' } + } + steps { + sh './run_tests.sh' } } - - } catch (e) { - currentBuild.result = "FAILURE" - throw e - } finally { - } } diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..f2cd731 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,11 @@ +FROM registry.fedoraproject.org/fedora:rawhide + +LABEL maintainer="Stephen Gallagher " + +RUN dnf -y --setopt=install_weak_deps=False install \ + git-core \ + make \ + python3-libmodulemd \ + python3-libmodulemd1 \ + python3-GitPython \ + && dnf -y clean all diff --git a/Makefile b/Makefile deleted file mode 100644 index 775b12c..0000000 --- a/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -check: - @python3 tests/validate.py diff --git a/run_tests.sh b/run_tests.sh old mode 100644 new mode 100755 index 25c8a97..0c323d9 --- a/run_tests.sh +++ b/run_tests.sh @@ -1,18 +1,30 @@ #!/bin/bash +set -e + if [ -n "$REPO" -a -n "$BRANCH" ]; then -git remote rm proposed || true -git gc --auto -git remote add proposed "$REPO" -git fetch proposed -git checkout origin/master -git config --global user.email "noreply@ci.centos.org" -git config --global user.name "CentOS CI" -git merge --no-ff "proposed/$BRANCH" -m "Merge PR" + git config user.email "noreply@ci.centos.org" + git config user.name "CentOS CI" + + # Save the commit ID of the baseline checkout + MODULE_DEFAULTS_TEST_BASELINE=$(git log -1 --pretty=%H) + export MODULE_DEFAULTS_TEST_BASELINE + + # Merge the PR into the current tree + git remote rm proposed || true + git gc --auto + git remote add proposed "$REPO" + git fetch proposed + git checkout origin/master + git merge --no-ff "proposed/$BRANCH" -m "Merge PR" + + echo "Running tests for branch $BRANCH of repo $REPO" + echo "Last commits:" + git log -2 -echo "Running tests for branch $BRANCH of repo $REPO" -echo "Last commits:" -git log -2 + # Run any tests that only apply to PRs + tests/pr_tests.sh fi -make check +# Run any tests that apply to either PRs or commits +tests/common_tests.sh diff --git a/tests/common_tests.sh b/tests/common_tests.sh new file mode 100755 index 0000000..4ebae25 --- /dev/null +++ b/tests/common_tests.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +set -e + +# Validate that all of the YAML documents are properly-named and have valid +# syntax. +python3 tests/validate.py diff --git a/tests/exclusions.txt b/tests/exclusions.txt index f111e68..9efd765 100644 --- a/tests/exclusions.txt +++ b/tests/exclusions.txt @@ -2,14 +2,16 @@ # Skip the CI integration bits .cico.pipeline +Dockerfile run_tests.sh -Makefile # Skip the README file README.md # Skip the validator files +tests/common_tests.sh tests/exclusions.txt +tests/pr_tests.sh tests/validate.py # Comment out the following when testing the validator @@ -19,4 +21,3 @@ tests/intents.yaml tests/missingstream.yaml tests/module.yaml tests/nodejs.yaml - diff --git a/tests/pr_tests.sh b/tests/pr_tests.sh new file mode 100755 index 0000000..47746e8 --- /dev/null +++ b/tests/pr_tests.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +set -e + +# Tests in this path may read the environment variable +# MODULE_DEFAULTS_TEST_BASELINE which specifies the commit ID that this PR has +# been applied atop. From f58233d57b5d09b9b7a4ba2187c655e11e0f0774 Mon Sep 17 00:00:00 2001 From: Stephen Gallagher Date: Jan 10 2019 20:11:27 +0000 Subject: [PATCH 2/5] WIP: Check modified files Signed-off-by: Stephen Gallagher --- diff --git a/tests/compare_defaults.py b/tests/compare_defaults.py new file mode 100755 index 0000000..b8c7fb5 --- /dev/null +++ b/tests/compare_defaults.py @@ -0,0 +1,106 @@ +#!/usr/bin/python3 + +import gi +import git +import os +import sys + +from gi.repository import GLib +gi.require_version('Modulemd', '2.0') +from gi.repository import Modulemd + +def print_failure(failure): + print("Error: %s" % failure.get_gerror()) + print("Offending YAML: \n%s" % failure.get_yaml()) + +def unusable_baseline(): + print("Baseline was unusable. Skipping test.") + return os.EX_OK + +def get_index_and_defaults (repo, filename, commit): + try: + yaml = repo.git.show('%s:%s' % (commit, filename)) + except git.exc.GitCommandError as e: + # This file didn't exist in the baseline commit, so just return + # success. If there's anything wrong with the new file, it will be + # caught in common_tests.sh + return 0 + + index = Modulemd.ModuleIndex.new() + try: + ret, failures = index.update_from_string(yaml, True) + if ret != True: + for failure in failures: + print_failure (failure) + raise IOError("Invalid modulemd-defaults document") + + except gi.repository.GLib.Error as e: + print ("Error: %s" % e) + raise IOError("Invalid YAML document") + + module_names = index.get_module_names() + if len(module_names) > 1: + raise IOError("YAML contained multiple modules") + elif len(module_names) < 1: + raise IOError("YAML contained no modules") + + defaults = index.get_module(index.get_module_names()[0]).get_defaults() + if not defaults: + raise IOError("YAML contained no defaults") + + return index, defaults + +def main(): + filename = sys.argv[1] + baseline_commit = sys.argv[2] + + script_dir = os.path.dirname(os.path.realpath(__file__)) + + repo = git.Repo(script_dir, + search_parent_directories=True) + + # First get the defaults from the baseline commit + try: + baseline_index, baseline_defaults = get_index_and_defaults ( + repo, filename, baseline_commit) + except IOError as e: + # This should never happen, since the original files presumably have + # been validated previously (unless someone merged without checking + # the CI results on a PR). If this occurs, the failures will be in the + # logs and we'll assume that this PR is trying to fix it, which will + # be mostly handled in common_tests.sh. + print(e, file=sys.stderr) + return unusable_baseline() + + try: + updated_commit = 'HEAD' + updated_index, updated_defaults = get_index_and_defaults ( + repo, filename, updated_commit) + except IOError as e: + # If we hit this, the patch is broken. + print(e, file=sys.stderr) + return os.EX_DATAERR + + if updated_defaults.get_modified() <= baseline_defaults.get_modified(): + print ("%s has changed but the 'modified' field has not increased." % + filename) + print ("Baseline modified: %d", baseline_defaults.get_modified()) + print ("Updated modified: %d", updated_defaults.get_modified()) + return os.EX_DATAERR + + # Confirm that these two sets of defaults merge cleanly + merger = Modulemd.ModuleIndexMerger.new() + merger.associate_index(baseline_index, 0) + merger.associate_index(baseline_index, 0) + + try: + merger.resolve() + except gi.repository.GLib.Error as e: + print ("Merge Error: %s" % e, file=sys.stderr) + return os.EX_DATAERR + + return os.EX_OK + +if __name__ == "__main__": + sys.exit(main()) + diff --git a/tests/exclusions.txt b/tests/exclusions.txt index 9efd765..8689e3d 100644 --- a/tests/exclusions.txt +++ b/tests/exclusions.txt @@ -10,6 +10,7 @@ README.md # Skip the validator files tests/common_tests.sh +tests/compare_defaults.py tests/exclusions.txt tests/pr_tests.sh tests/validate.py diff --git a/tests/pr_tests.sh b/tests/pr_tests.sh index 47746e8..027ca83 100755 --- a/tests/pr_tests.sh +++ b/tests/pr_tests.sh @@ -2,6 +2,27 @@ set -e +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + # Tests in this path may read the environment variable # MODULE_DEFAULTS_TEST_BASELINE which specifies the commit ID that this PR has # been applied atop. + +# Set the $CWD to the root of this repo +GIT_ROOT=$(git rev-parse --show-toplevel) +pushd $GIT_ROOT + +# Get a list of changed files +modified_files=$(git log --name-only \ + --pretty=oneline \ + --full-index \ + $MODULE_DEFAULTS_TEST_BASELINE..HEAD \ + | grep -vE '^[0-9a-f]{40} ' | sort -u) + +for file in ${modified_files[@]}; do + if [[ $file == *".yaml" ]]; then + $SCRIPT_DIR/compare_defaults.py $file $MODULE_DEFAULTS_TEST_BASELINE + fi +done + +popd From c025300c58056da1e3e129785c4f0b9672217f9a Mon Sep 17 00:00:00 2001 From: Stephen Gallagher Date: Jan 10 2019 20:16:21 +0000 Subject: [PATCH 3/5] Debugging Signed-off-by: Stephen Gallagher --- diff --git a/tests/compare_defaults.py b/tests/compare_defaults.py index b8c7fb5..ad7b5e5 100755 --- a/tests/compare_defaults.py +++ b/tests/compare_defaults.py @@ -51,6 +51,7 @@ def get_index_and_defaults (repo, filename, commit): return index, defaults def main(): + os.putenv('G_MESSAGES_DEBUG', 'all') filename = sys.argv[1] baseline_commit = sys.argv[2] From 3b65f72030b731a4e7ed5773ff152e1f091e86b6 Mon Sep 17 00:00:00 2001 From: Stephen Gallagher Date: Jan 14 2019 14:28:52 +0000 Subject: [PATCH 4/5] Force pull docker image every build Signed-off-by: Stephen Gallagher --- diff --git a/.cico.pipeline b/.cico.pipeline index 17182cc..159a818 100644 --- a/.cico.pipeline +++ b/.cico.pipeline @@ -9,7 +9,10 @@ pipeline { stages { stage('Validate Content') { agent { - dockerfile { label 'fedora29' } + dockerfile { + label 'fedora29' + additionalBuildArgs "--pull --no-cache" + } } steps { sh './run_tests.sh' From 27375773c0aa0b2432c8e984cc5fa6d58817e0f0 Mon Sep 17 00:00:00 2001 From: Stephen Gallagher Date: Jan 15 2019 14:02:14 +0000 Subject: [PATCH 5/5] Test commit Signed-off-by: Stephen Gallagher --- diff --git a/dwm.yaml b/dwm.yaml index 2cf9d5a..3d7cb68 100644 --- a/dwm.yaml +++ b/dwm.yaml @@ -2,8 +2,10 @@ document: modulemd-defaults version: 1 data: module: dwm - stream: 6.1 + stream: 6.2 + modified: 20180110 profiles: 6.0: [default] 6.1: [default] + 6.2: [default] latest: [default] diff --git a/gimp.yaml b/gimp.yaml index 04663db..d803955 100644 --- a/gimp.yaml +++ b/gimp.yaml @@ -2,6 +2,7 @@ document: modulemd-defaults version: 1 data: module: gimp - stream: 2.10 + stream: 2.12 + modified: 201901151200 profiles: - 2.10: [default] + 2.12: [default] \ No newline at end of file diff --git a/tests/validate.py b/tests/validate.py index c8f9887..86b8e87 100755 --- a/tests/validate.py +++ b/tests/validate.py @@ -10,6 +10,8 @@ from gi.repository import GLib gi.require_version('Modulemd', '1.0') from gi.repository import Modulemd +# Useless comment to test filtering + def do_validate(filename): # Valid filenames must end in ".yaml" to be properly included by Pungi if not filename.endswith(".yaml"): @@ -137,4 +139,4 @@ def main(): return result if __name__ == "__main__": - sys.exit(main()) \ No newline at end of file + sys.exit(main())