From aac8552b753a354b6c7cfea7c17da58b8fdceaf2 Mon Sep 17 00:00:00 2001 From: Timo Koch Date: Mon, 23 Nov 2020 17:53:47 +0100 Subject: [PATCH 01/25] [cmake] Write test meta data to file for CI --- cmake/modules/DumuxTestMacros.cmake | 55 +++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/cmake/modules/DumuxTestMacros.cmake b/cmake/modules/DumuxTestMacros.cmake index a892127279..ba9fa59f35 100644 --- a/cmake/modules/DumuxTestMacros.cmake +++ b/cmake/modules/DumuxTestMacros.cmake @@ -204,6 +204,61 @@ # future Dune features with older Dune versions supported by Dumux function(dumux_add_test) dune_add_test(${ARGV}) + + include(CMakeParseArguments) + set(OPTIONS EXPECT_COMPILE_FAIL EXPECT_FAIL SKIP_ON_77 COMPILE_ONLY) + set(SINGLEARGS NAME TARGET TIMEOUT) + set(MULTIARGS SOURCES COMPILE_DEFINITIONS COMPILE_FLAGS LINK_LIBRARIES CMD_ARGS MPI_RANKS COMMAND CMAKE_GUARD LABELS) + cmake_parse_arguments(ADDTEST "${OPTIONS}" "${SINGLEARGS}" "${MULTIARGS}" ${ARGN}) + + if(NOT ADDTEST_NAME) + # try deducing the test name from the executable name + if(ADDTEST_TARGET) + set(ADDTEST_NAME ${ADDTEST_TARGET}) + endif() + # try deducing the test name form the source name + if(ADDTEST_SOURCES) + # deducing a name is only possible with a single source argument + list(LENGTH ADDTEST_SOURCES len) + if(NOT len STREQUAL "1") + message(FATAL_ERROR "Cannot deduce test name from multiple sources!") + endif() + # strip file extension + get_filename_component(ADDTEST_NAME ${ADDTEST_SOURCES} NAME_WE) + endif() + endif() + if(NOT ADDTEST_COMMAND) + set(ADDTEST_COMMAND ${ADDTEST_NAME}) + endif() + + # Find out whether this test should be a dummy + set(SHOULD_SKIP_TEST FALSE) + set(FAILED_CONDITION_PRINTING "") + foreach(condition ${ADDTEST_CMAKE_GUARD}) + separate_arguments(condition) + if(NOT (${condition})) + set(SHOULD_SKIP_TEST TRUE) + set(FAILED_CONDITION_PRINTING "${FAILED_CONDITION_PRINTING}std::cout << \" ${condition}\" << std::endl;\n") + endif() + endforeach() + + # If we do nothing, switch the sources for a dummy source + if(SHOULD_SKIP_TEST) + dune_module_path(MODULE dune-common RESULT scriptdir SCRIPT_DIR) + set(ADDTEST_TARGET) + set(dummymain ${CMAKE_CURRENT_BINARY_DIR}/main77_${ADDTEST_NAME}.cc) + configure_file(${scriptdir}/main77.cc.in ${dummymain}) + set(ADDTEST_SOURCES ${dummymain}) + endif() + + # Add the executable if it is not already present + if(ADDTEST_SOURCES) + set(ADDTEST_TARGET ${ADDTEST_NAME}) + endif() + + file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/TestMetaData") + file(WRITE "${CMAKE_BINARY_DIR}/TestMetaData/${ADDTEST_NAME}.json" + "\{\n \"name\": \"${ADDTEST_NAME}\",\n \"target\": \"${ADDTEST_TARGET}\"\n\}\n") endfunction() # Evaluate test guards like dune_add_test internally does -- GitLab From 00376dcc2a8c1a3ee24284585319ea5e7ff92306 Mon Sep 17 00:00:00 2001 From: Timo Koch Date: Tue, 24 Nov 2020 10:33:09 +0100 Subject: [PATCH 02/25] [test] Add script to identify tests that are affected by a change --- bin/testing/findtests.py | 69 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100755 bin/testing/findtests.py diff --git a/bin/testing/findtests.py b/bin/testing/findtests.py new file mode 100755 index 0000000000..676a297f91 --- /dev/null +++ b/bin/testing/findtests.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python3 + +""" +Find those tests that are affected by changes +Run this in the build directory +Warning: This runs 'make clean' on the build directory +""" + +import multiprocessing as mp +import json +import subprocess +from glob import glob +from subprocess import PIPE +import os + +import sys + +# Whether the two lists a and b have a common member +def has_common_member(myset, mylist): + return not myset.isdisjoint(mylist) + +def make_dryrun(config): + lines = subprocess.check_output(["make", "--dry-run", config["target"]], encoding='ascii').splitlines() + return [l for l in lines if "g++" in l] + +def build_command_and_dir(config, cache): + lines = make_dryrun(config) + if len(lines) == 0: + with open(cache) as c: + data = json.load(c) + return data["command"], data["dir"] + else: + (_, dir), command = [l.split() for l in lines[0].split("&&")] + with open(cache, "w") as c: + json.dump({"command":command, "dir":dir}, c) + + return command, dir + +# find the changes files +changed_files = subprocess.check_output(["git", "diff-tree", "-r", "--name-only", "HEAD", "master"], encoding='ascii').splitlines() +changed_files = set(changed_files) + +def is_affected_tests(test): + with open(test) as config_file: + config = json.load(config_file) + + command, dir = build_command_and_dir(config, "TestTargets/"+config["target"]+".json") + # for some reason g++ writes to stderr + lines = subprocess.run(command + ["-MM", "-H"], stderr=PIPE, stdout=PIPE, cwd=dir, encoding='ascii').stderr.splitlines() + + # filter lines + project_dir = os.path.abspath(os.getcwd().rstrip("build-cmake")) + test_files = set([os.path.relpath(l.lstrip(". "), project_dir) for l in lines if project_dir in l]) + + if has_common_member(changed_files, test_files): + return True, config["name"], config["target"] + + return False, config["name"], config["target"] + +if __name__ == '__main__': + + subprocess.run(["make", "clean"]) + subprocess.run(["make"]) + + # create cache folder + os.makedirs("TestTargets", exist_ok=True) + + for test in glob("TestMetaData/*json"): + print(is_affected_tests(test)) -- GitLab From e3b2abc526d88799e7c0cbe935a2f38ab86bb9a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dennis=20Gl=C3=A4ser?= Date: Mon, 12 Apr 2021 13:31:58 +0200 Subject: [PATCH 03/25] [bin][test] pass changed files to function --- bin/testing/findtests.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/bin/testing/findtests.py b/bin/testing/findtests.py index 676a297f91..ec80ffd8f8 100755 --- a/bin/testing/findtests.py +++ b/bin/testing/findtests.py @@ -36,11 +36,7 @@ def build_command_and_dir(config, cache): return command, dir -# find the changes files -changed_files = subprocess.check_output(["git", "diff-tree", "-r", "--name-only", "HEAD", "master"], encoding='ascii').splitlines() -changed_files = set(changed_files) - -def is_affected_tests(test): +def is_affected_test(test, changed_files): with open(test) as config_file: config = json.load(config_file) @@ -59,6 +55,10 @@ def is_affected_tests(test): if __name__ == '__main__': + # find the changes files + changed_files = subprocess.check_output(["git", "diff-tree", "-r", "--name-only", "HEAD", "master"], encoding='ascii').splitlines() + changed_files = set(changed_files) + subprocess.run(["make", "clean"]) subprocess.run(["make"]) @@ -66,4 +66,4 @@ if __name__ == '__main__': os.makedirs("TestTargets", exist_ok=True) for test in glob("TestMetaData/*json"): - print(is_affected_tests(test)) + print(is_affected_test(test, changed_files)) -- GitLab From 9b824c39365652ca63372c6b1d8f1cb092759b52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dennis=20Gl=C3=A4ser?= Date: Mon, 12 Apr 2021 13:45:23 +0200 Subject: [PATCH 04/25] [bi][test] make source/target tree settable --- bin/testing/findtests.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/bin/testing/findtests.py b/bin/testing/findtests.py index ec80ffd8f8..7adb022561 100755 --- a/bin/testing/findtests.py +++ b/bin/testing/findtests.py @@ -9,6 +9,7 @@ Warning: This runs 'make clean' on the build directory import multiprocessing as mp import json import subprocess +from argparse import ArgumentParser from glob import glob from subprocess import PIPE import os @@ -53,10 +54,23 @@ def is_affected_test(test, changed_files): return False, config["name"], config["target"] + if __name__ == '__main__': + # parse input arguments + parser = ArgumentParser(description='Find tests affected by changes') + parser.add_argument('-s', '--source', required=False, default='HEAD', + help='The source tree (default: `HEAD`)') + parser.add_argument('-t', '--target', required=False, default='master', + help='The tree to compare against (default: `master`)') + + args = vars(parser.parse_args()) + # find the changes files - changed_files = subprocess.check_output(["git", "diff-tree", "-r", "--name-only", "HEAD", "master"], encoding='ascii').splitlines() + changed_files = subprocess.check_output(["git", "diff-tree", + "-r", "--name-only", + args['source'], args['target']], + encoding='ascii').splitlines() changed_files = set(changed_files) subprocess.run(["make", "clean"]) -- GitLab From a774bc228542fcf96c5af538eea35ae342eb8f5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dennis=20Gl=C3=A4ser?= Date: Mon, 12 Apr 2021 13:46:07 +0200 Subject: [PATCH 05/25] [bin][findtests] remove obsolete imports --- bin/testing/findtests.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/bin/testing/findtests.py b/bin/testing/findtests.py index 7adb022561..93207099c3 100755 --- a/bin/testing/findtests.py +++ b/bin/testing/findtests.py @@ -6,7 +6,6 @@ Run this in the build directory Warning: This runs 'make clean' on the build directory """ -import multiprocessing as mp import json import subprocess from argparse import ArgumentParser @@ -14,8 +13,6 @@ from glob import glob from subprocess import PIPE import os -import sys - # Whether the two lists a and b have a common member def has_common_member(myset, mylist): return not myset.isdisjoint(mylist) -- GitLab From 564451e2e2a85c12283c0649e5501fd636726719 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dennis=20Gl=C3=A4ser?= Date: Mon, 12 Apr 2021 14:30:29 +0200 Subject: [PATCH 06/25] [bin][findtest] rearrange and comply with PEP8 style --- bin/testing/findtests.py | 76 +++++++++++++++++++++++++++++----------- 1 file changed, 55 insertions(+), 21 deletions(-) diff --git a/bin/testing/findtests.py b/bin/testing/findtests.py index 93207099c3..c1f970addd 100755 --- a/bin/testing/findtests.py +++ b/bin/testing/findtests.py @@ -13,43 +13,65 @@ from glob import glob from subprocess import PIPE import os + # Whether the two lists a and b have a common member def has_common_member(myset, mylist): return not myset.isdisjoint(mylist) -def make_dryrun(config): - lines = subprocess.check_output(["make", "--dry-run", config["target"]], encoding='ascii').splitlines() - return [l for l in lines if "g++" in l] -def build_command_and_dir(config, cache): - lines = make_dryrun(config) - if len(lines) == 0: +# make dry run and return the compilation command +def get_compile_command(testConfig): + lines = subprocess.check_output(["make", "--dry-run", + testConfig["target"]], + encoding='ascii').splitlines() + commands = list(filter(lambda comm: 'g++' in comm, lines)) + assert len(commands) <= 1 + return commands[0] if commands else None + + +# get the command and folder to compile the given test +def build_command_and_dir(testConfig, cache): + compCommand = get_compile_command(testConfig) + if compCommand is None: with open(cache) as c: data = json.load(c) return data["command"], data["dir"] else: - (_, dir), command = [l.split() for l in lines[0].split("&&")] + (_, dir), command = [comm.split() for comm in compCommand.split("&&")] with open(cache, "w") as c: - json.dump({"command":command, "dir":dir}, c) + json.dump({"command": command, "dir": dir}, c) + return command, dir + - return command, dir +# check if a test is affected by changes in the given files +def is_affected_test(testConfigFile, changed_files): + with open(testConfigFile) as configFile: + testConfig = json.load(configFile) -def is_affected_test(test, changed_files): - with open(test) as config_file: - config = json.load(config_file) + cacheFile = "TestTargets/" + testConfig["target"] + ".json" + command, dir = build_command_and_dir(testConfig, cacheFile) - command, dir = build_command_and_dir(config, "TestTargets/"+config["target"]+".json") + # detect headers included in this test + # -MM skips headers from system directories + # -H prints the name(+path) of each used header # for some reason g++ writes to stderr - lines = subprocess.run(command + ["-MM", "-H"], stderr=PIPE, stdout=PIPE, cwd=dir, encoding='ascii').stderr.splitlines() + headers = subprocess.run(command + ["-MM", "-H"], + stderr=PIPE, stdout=PIPE, cwd=dir, + encoding='ascii').stderr.splitlines() - # filter lines - project_dir = os.path.abspath(os.getcwd().rstrip("build-cmake")) - test_files = set([os.path.relpath(l.lstrip(". "), project_dir) for l in lines if project_dir in l]) + # filter only headers from this project and turn them into relative paths + projectDir = os.path.abspath(os.getcwd().rstrip("build-cmake")) + + def isProjectHeader(headerPath): + return projectDir in headerPath + + test_files = set([os.path.relpath(header.lstrip(". "), projectDir) + for header in filter(isProjectHeader, headers)]) if has_common_member(changed_files, test_files): - return True, config["name"], config["target"] + return True, testConfig["name"], testConfig["target"] - return False, config["name"], config["target"] + return False, testConfig["name"], testConfig["target"] if __name__ == '__main__': @@ -60,7 +82,6 @@ if __name__ == '__main__': help='The source tree (default: `HEAD`)') parser.add_argument('-t', '--target', required=False, default='master', help='The tree to compare against (default: `master`)') - args = vars(parser.parse_args()) # find the changes files @@ -70,11 +91,24 @@ if __name__ == '__main__': encoding='ascii').splitlines() changed_files = set(changed_files) + # clean build directory subprocess.run(["make", "clean"]) subprocess.run(["make"]) # create cache folder os.makedirs("TestTargets", exist_ok=True) + # detect affected tests + print("Detecting affected tests:") + count = 0 + affectedTests = {} for test in glob("TestMetaData/*json"): - print(is_affected_test(test, changed_files)) + affected, name, target = is_affected_test(test, changed_files) + if affected: + print("\t- {}".format(name)) + affectedTests[name] = {'target': target} + count += 1 + print("Detected {} affected tests".format(count)) + + with open('affectedtests.json', 'w') as jsonFile: + json.dump(affectedTests, jsonFile) -- GitLab From 4bd1beb459873128dc57309b83d8ef8437261daa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dennis=20Gl=C3=A4ser?= Date: Mon, 12 Apr 2021 15:02:27 +0200 Subject: [PATCH 07/25] [bin][findtests] make output file settable --- bin/testing/findtests.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/bin/testing/findtests.py b/bin/testing/findtests.py index c1f970addd..aa9bf51557 100755 --- a/bin/testing/findtests.py +++ b/bin/testing/findtests.py @@ -14,7 +14,7 @@ from subprocess import PIPE import os -# Whether the two lists a and b have a common member +# Check if the set a contains a member of list b def has_common_member(myset, mylist): return not myset.isdisjoint(mylist) @@ -82,6 +82,9 @@ if __name__ == '__main__': help='The source tree (default: `HEAD`)') parser.add_argument('-t', '--target', required=False, default='master', help='The tree to compare against (default: `master`)') + parser.add_argument('-f', '--outfile', required=False, + default='affectedtests.json', + help='The file in which to write the affected tests') args = vars(parser.parse_args()) # find the changes files @@ -110,5 +113,5 @@ if __name__ == '__main__': count += 1 print("Detected {} affected tests".format(count)) - with open('affectedtests.json', 'w') as jsonFile: + with open(args['outfile'], 'w') as jsonFile: json.dump(affectedTests, jsonFile) -- GitLab From c2d05712e944709b9784af5f1c555d5ff9b95f1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dennis=20Gl=C3=A4ser?= Date: Tue, 13 Apr 2021 17:21:23 +0200 Subject: [PATCH 08/25] [bin][findtest] use camelcase names --- bin/testing/findtests.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/bin/testing/findtests.py b/bin/testing/findtests.py index aa9bf51557..daa006ac45 100755 --- a/bin/testing/findtests.py +++ b/bin/testing/findtests.py @@ -15,12 +15,12 @@ import os # Check if the set a contains a member of list b -def has_common_member(myset, mylist): +def hasCommonMember(myset, mylist): return not myset.isdisjoint(mylist) # make dry run and return the compilation command -def get_compile_command(testConfig): +def getCompileCommand(testConfig): lines = subprocess.check_output(["make", "--dry-run", testConfig["target"]], encoding='ascii').splitlines() @@ -30,8 +30,8 @@ def get_compile_command(testConfig): # get the command and folder to compile the given test -def build_command_and_dir(testConfig, cache): - compCommand = get_compile_command(testConfig) +def buildCommandAndDir(testConfig, cache): + compCommand = getCompileCommand(testConfig) if compCommand is None: with open(cache) as c: data = json.load(c) @@ -44,12 +44,12 @@ def build_command_and_dir(testConfig, cache): # check if a test is affected by changes in the given files -def is_affected_test(testConfigFile, changed_files): +def isAffectedTest(testConfigFile, changed_files): with open(testConfigFile) as configFile: testConfig = json.load(configFile) cacheFile = "TestTargets/" + testConfig["target"] + ".json" - command, dir = build_command_and_dir(testConfig, cacheFile) + command, dir = buildCommandAndDir(testConfig, cacheFile) # detect headers included in this test # -MM skips headers from system directories @@ -68,7 +68,7 @@ def is_affected_test(testConfigFile, changed_files): test_files = set([os.path.relpath(header.lstrip(". "), projectDir) for header in filter(isProjectHeader, headers)]) - if has_common_member(changed_files, test_files): + if hasCommonMember(changed_files, test_files): return True, testConfig["name"], testConfig["target"] return False, testConfig["name"], testConfig["target"] @@ -106,7 +106,7 @@ if __name__ == '__main__': count = 0 affectedTests = {} for test in glob("TestMetaData/*json"): - affected, name, target = is_affected_test(test, changed_files) + affected, name, target = isAffectedTest(test, changed_files) if affected: print("\t- {}".format(name)) affectedTests[name] = {'target': target} -- GitLab From 65e2210ff62f550a104c7927d71056d23276abd3 Mon Sep 17 00:00:00 2001 From: "Dennis.Glaeser" Date: Mon, 23 Nov 2020 19:08:17 +0100 Subject: [PATCH 09/25] [ci] add default pipeline config --- .gitlab-ci/default.yml | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 .gitlab-ci/default.yml diff --git a/.gitlab-ci/default.yml b/.gitlab-ci/default.yml new file mode 100644 index 0000000000..f70144c0a5 --- /dev/null +++ b/.gitlab-ci/default.yml @@ -0,0 +1,29 @@ +default: + image: $IMAGE + +stages: + - build + - test + +workflow: + rules: + - if: $CI_PIPELINE_SOURCE=="parent_pipeline" + +build dumux: + stage: build + script: + - dunecontrol --opts=$DUNE_OPTS_FILE --current all + - dunecontrol --opts=$DUNE_OPTS_FILE --current make -k -j8 build_tests + artifacts: + paths: + - build-cmake + expire_in: 3 hours + +test dumux: + stage: test + script: + - cd build-cmake + - dune-ctest -j8 --no-tests=error + needs: + - job: build dumux + artifacts: true -- GitLab From f7270f29bf565f0f21069100b5ed32cab37015e2 Mon Sep 17 00:00:00 2001 From: "Dennis.Glaeser" Date: Mon, 23 Nov 2020 19:14:38 +0100 Subject: [PATCH 10/25] [ci] add yml file for ci config --- .gitlab-ci.yml | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 .gitlab-ci.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000000..08d2d2ae8b --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,68 @@ +stages: + - trigger pipelines + - trigger downstream modules + +variables: + IMAGE_REGISTRY_URL: $CI_REGISTRY/dumux-repositories/dumux-docker-ci + +# rules for pipelines: +# - pipelines are triggered for commits to master, tags, merge requests +# - Within merge requests, we require to start the pipeline manually +# by clicking play for the trigger +.default-trigger: + stage: trigger pipelines + trigger: + include: + - local: .gitlab-ci/default.yml + strategy: depend + rules: + - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH + - if: $CI_PIPELINE_SOURCE == "pipeline" + - if: $CI_PIPELINE_SOURCE == "merge_request_event" + when: manual + +.scheduled-trigger: + extends: .default-trigger + rules: + - if: $CI_PIPELINE_SOURCE == "schedule" + +################################### +# pipelines with different setups # +full-dune-2.7-gcc: + extends: .default-trigger + variables: + IMAGE: $IMAGE_REGISTRY_URL/full:dune-2.7-gcc-ubuntu-20.04 + +minimal-dune-2.7-gcc: + extends: .default-trigger + variables: + IMAGE: $IMAGE_REGISTRY_URL/minimal:dune-2.7-gcc-ubuntu-20.04 + +full-dune-2.7-clang: + extends: .default-trigger + variables: + IMAGE: $IMAGE_REGISTRY_URL/full:dune-2.7-clang-ubuntu-20.04 + +################################## +# additional scheduled pipelines # +full-dune-master-gcc: + extends: .scheduled-trigger + variables: + IMAGE: $IMAGE_REGISTRY_URL/full:dune-master-gcc-ubuntu-20.04 + +full-dune-master-clang: + extends: .scheduled-trigger + variables: + IMAGE: $IMAGE_REGISTRY_URL/full:dune-master-clang-ubuntu-20.04 + +################################### +# triggers for downstream modules # +trigger lecture: + stage: trigger downstream modules + trigger: + project: dumux-repositories/dumux-lecture + # TODO: replace by master once development in lecture is finished + branch: feature/test-dumux-trigger + strategy: depend + variables: + DUMUX_BRANCH_NAME: $CI_COMMIT_BRANCH -- GitLab From 621bd9107483407ad70235c35ec23f1b14f29b43 Mon Sep 17 00:00:00 2001 From: "Dennis.Glaeser" Date: Mon, 14 Dec 2020 16:44:08 +0100 Subject: [PATCH 11/25] [ci] report test results --- .gitlab-ci/default.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitlab-ci/default.yml b/.gitlab-ci/default.yml index f70144c0a5..421c25ae5a 100644 --- a/.gitlab-ci/default.yml +++ b/.gitlab-ci/default.yml @@ -27,3 +27,6 @@ test dumux: needs: - job: build dumux artifacts: true + artifacts: + reports: + junit: junit/dumux-cmake.xml -- GitLab From 7975ee19c6e47b7e2c25a51232683600da08b8b7 Mon Sep 17 00:00:00 2001 From: "Dennis.Glaeser" Date: Tue, 15 Dec 2020 17:52:17 +0100 Subject: [PATCH 12/25] [ci] change branch variable for downstream module trigger --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 08d2d2ae8b..70bb147464 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -65,4 +65,4 @@ trigger lecture: branch: feature/test-dumux-trigger strategy: depend variables: - DUMUX_BRANCH_NAME: $CI_COMMIT_BRANCH + DUMUX_BRANCH: $CI_COMMIT_BRANCH -- GitLab From fe30315ebee46c6c942b5c239843c62b7f519400 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dennis=20Gl=C3=A4ser?= Date: Mon, 12 Apr 2021 17:16:07 +0200 Subject: [PATCH 13/25] [bin][test] add script to run a selection of tests --- bin/testing/runselectedtests.py | 116 ++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 bin/testing/runselectedtests.py diff --git a/bin/testing/runselectedtests.py b/bin/testing/runselectedtests.py new file mode 100644 index 0000000000..75cb94f2d8 --- /dev/null +++ b/bin/testing/runselectedtests.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python3 + +""" +Build and/or run (using `dune-ctest`) a selection of tests. +Run this in the top level of the build tree. +""" + +import sys +import json +import subprocess +from argparse import ArgumentParser + +# require Python 3 +if sys.version_info.major < 3: + sys.exit('Python 3 required') + + +def buildTests(config, flags=['j4']): + + if not config: + print('No tests to be built') + return + + # The MakeFile generated by cmake contains the .NOTPARALLEL statement, as + # it only allows one call to `CMakeFiles/Makefile2` at a time. Parallelism + # is taken care of within that latter Makefile. Therefore, we create a + # small custom Makefile here on top of `Makefile2`, where we define a new + # target, composed of affected tests, that can be built in parallel + with open('TestMakeFile', 'w') as makeFile: + # include make file generated by cmake + makeFile.write('include CMakeFiles/Makefile2\n') + + # define a new target composed of the test targets + makeFile.write('testselection: ') + makeFile.write(' '.join([tc['target'] for tc in config.values()])) + + subprocess.run(['make', '-f', 'TestMakeFile'] + flags + ['testselection'], + check=True) + + +def runTests(config, script='', flags=['-j4', '--output-on-failure']): + + tests = list(config.keys()) + if not tests: + print('No tests to be run. Letting dune-ctest produce empty report.') + tests = ['NOOP'] + + # if not given, try system-wide call to dune-ctest + call = ['dune-ctest'] if not script else ['./' + script.lstrip('./')] + call.extend(flags) + call.extend(['-R'] + tests) + subprocess.run(call, check=True) + + +if __name__ == '__main__': + parser = ArgumentParser(description='Build or run a selection of tests') + parser.add_argument('-a', '--all', + required=False, + action='store_true', + help='use this flag to build/run all tests') + parser.add_argument('-c', '--config', + required=False, + help='json file with configuration of tests to be run') + parser.add_argument('-s', '--script', + required=False, + default='', + help='provide the path to the dune-ctest script') + parser.add_argument('-b', '--build', + required=False, + action='store_true', + help='use this flag to build the tests') + parser.add_argument('-t', '--test', + required=False, + action='store_true', + help='use this flag to run the tests') + parser.add_argument('-bf', '--buildflags', + required=False, + default='-j4', + help='set the flags passed to make') + parser.add_argument('-tf', '--testflags', + required=False, + default='-j4 --output-on-failure', + help='set the flags passed to ctest') + args = vars(parser.parse_args()) + + if not args['build'] and not args['test']: + sys.exit('Neither `build` not `test` flag was set. Exiting.') + + if args['config'] and args['all']: + sys.exit('Error: both `config` and `all` specified. ' + 'Please set only one of these arguments.') + + # prepare build and test flags + buildFlags = args['buildflags'].split(' ') + testFlags = args['testflags'].split(' ') + + # use target `all` + if args['all']: + if args['build']: + print('Building all tests') + subprocess.run(['make'] + buildFlags + ['build_tests'], check=True) + if args['test']: + print('Running all tests') + subprocess.run(['ctest'] + testFlags, check=True) + + # use target selection + else: + with open(args['config']) as configFile: + config = json.load(configFile) + numTests = len(config) + print('{} tests found in the configuration file'.format(numTests)) + + if args['build']: + buildTests(config, buildFlags) + if args['test']: + runTests(config, args['script'], testFlags) -- GitLab From 4786e2ec83ea495060417d50f5a12ef1e0728f76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dennis=20Gl=C3=A4ser?= Date: Tue, 13 Apr 2021 16:01:07 +0200 Subject: [PATCH 14/25] [ci] add script to create .yml file from test config --- .gitlab-ci/default.yml.template | 30 +++++++++++++ .gitlab-ci/makepipelineconfig.py | 77 ++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 .gitlab-ci/default.yml.template create mode 100644 .gitlab-ci/makepipelineconfig.py diff --git a/.gitlab-ci/default.yml.template b/.gitlab-ci/default.yml.template new file mode 100644 index 0000000000..29095ff05d --- /dev/null +++ b/.gitlab-ci/default.yml.template @@ -0,0 +1,30 @@ +default: + image: $$IMAGE + +stages: + - build + - test + +workflow: + rules: + - if: $$CI_PIPELINE_SOURCE=="parent_pipeline" + +build dumux: + stage: build + script: +${build_script} + artifacts: + paths: + - build-cmake + expire_in: 3 hours + +test dumux: + stage: test + script: +${test_script} + needs: + - job: build dumux + artifacts: true + artifacts: + reports: + junit: junit/dumux-cmake.xml diff --git a/.gitlab-ci/makepipelineconfig.py b/.gitlab-ci/makepipelineconfig.py new file mode 100644 index 0000000000..80b4598017 --- /dev/null +++ b/.gitlab-ci/makepipelineconfig.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python3 + +import os +import sys +import json +import string +from argparse import ArgumentParser + +# require Python 3 +if sys.version_info.major < 3: + sys.exit('Python 3 required') + +parser = ArgumentParser(description='Generate dumux test pipeline .yml file') +parser.add_argument('-o', '--outfile', required=True, + help='Specify the file to write the pipeline definition') +parser.add_argument('-c', '--testconfig', required=False, + help='Specify a test configuration file containing the ' + 'tests that should be run within the test pipeline') +parser.add_argument('-t', '--template', required=False, + default='.gitlab-ci/default.yml.template', + help='Specify the template .yml file to be used') +parser.add_argument('-i', '--indentation', required=False, default=4, + help='Specify the indentation for the script commands') +args = vars(parser.parse_args()) + + +# substitute content from template and write to target +def substituteAndWrite(mapping): + + template = args['template'] + if not os.path.exists(template): + sys.exit("Template file '" + template + "' could not be found") + + with open(args['outfile'], 'w') as ymlFile: + raw = string.Template(open(template).read()) + ymlFile.write(raw.substitute(**mapping)) + + +with open(args['outfile'], 'w') as ymlFile: + + def makeScriptString(commands): + commands = [' '*args['indentation'] + '- ' + comm for comm in commands] + return '\n'.join(commands) + + # if no configuration is given, build and run all tests + if not args['testconfig']: + buildCommand = ['dunecontrol --opts=$DUNE_OPTS_FILE --current all', + 'dunecontrol --opts=$DUNE_OPTS_FILE --current ' + 'make -k -j4 build_tests'] + testCommand = ['cd build-cmake', 'dune-ctest -j4 --output-on-failure'] + + # otherwise, parse data from the given configuration file + else: + with open(args['testconfig']) as configFile: + config = json.load(configFile) + + testNames = config.keys() + targetNames = [tc['target'] for tc in config.values()] + + # The MakeFile generated by cmake contains .NOTPARALLEL statement, + # as it only allows one call to `CMakeFiles/Makefile2` at a time. + # Parallelism is taken care of within that latter Makefile. Thus, + # we let the script create a small custom makeFile here on top of + # `Makefile2`, where we define a new target to be built in parallel + buildCommand = [ + 'rm TestMakefile', 'touch TestMakefile', + 'echo "include CMakeFiles/Makefile2" >> TestMakefile', + 'echo "" >> TestMakefile', + 'echo "build_selected_tests: {}" >> TestMakefile' + .format(' '.join(targetNames)), + 'make -j4 build_selected_tests'] + testCommand = ['cd build-cmake', + 'dune-ctest -j4 --output-on-failure -R {}' + .format(' '.join(testNames))] + + substituteAndWrite({'build_script': makeScriptString(buildCommand), + 'test_script': makeScriptString(testCommand)}) -- GitLab From a7fc04123fe95472552c6762a73fd27991c37308 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dennis=20Gl=C3=A4ser?= Date: Tue, 13 Apr 2021 16:03:03 +0200 Subject: [PATCH 15/25] [ci] make yml configuration on-the-fly --- .gitlab-ci.yml | 106 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 72 insertions(+), 34 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 70bb147464..0418c45316 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,68 +1,106 @@ stages: - - trigger pipelines - - trigger downstream modules + - pipeline config + - test pipelines + # - downstream modules variables: IMAGE_REGISTRY_URL: $CI_REGISTRY/dumux-repositories/dumux-docker-ci -# rules for pipelines: -# - pipelines are triggered for commits to master, tags, merge requests -# - Within merge requests, we require to start the pipeline manually -# by clicking play for the trigger -.default-trigger: - stage: trigger pipelines - trigger: - include: - - local: .gitlab-ci/default.yml - strategy: depend +workflow: rules: + - if: $CI_PIPELINE_SOURCE == "schedule" - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH - - if: $CI_PIPELINE_SOURCE == "pipeline" + when: manual - if: $CI_PIPELINE_SOURCE == "merge_request_event" when: manual -.scheduled-trigger: - extends: .default-trigger +################################################################################### +# Stage 1: configure the test pipeline. # +# This creates the .yml to be used for the test pipeline trigger stage. Within # +# merge request, we create a .yml file that considers building and executing only # +# those test that are affected by the changes introduced in the merge request. # +# In all other cases, we use the default configuration which runs all tests. # +################################################################################### +generate-config: + image: $IMAGE_REGISTRY_URL/full:dune-2.7-gcc-ubuntu-20.04 + stage: pipeline config + script: + - dunecontrol --opts=$DUNE_OPTS_FILE --current all + - | + if [ $CI_PIPELINE_SOURCE == "merge_request_event" ]; then + cd build-cmake + python3 ../bin/testing/findtests.py -f affectedtests.json -t origin/master + python3 ../.gitlab-ci/makepipelineconfig.py -c affectedtests.json -o ../generated-config.yml + else + python3 .gitlab-ci/makepipelineconfig.py -o generated-config.yml + fi + artifacts: + paths: + - generated-config.yml + expire_in: 3 hours + +################################################################################### +# Stage 2: trigger the test pipelines # +# In this stage, we trigger the test pipeline with different configurations, i.e. # +# different Dune versions, compilers, etc. Within merge requests, we create three # +# test pipelines including two different compilers and a full and minimal setup # +# of dependencies. In all other situations, additional test jobs are created. # +################################################################################### + +# basic trigger job to start the test pipeline +.base-trigger: + stage: test pipelines + needs: + - generate-config + trigger: + include: + - artifact: generated-config.yml + job: generate-config + strategy: depend + +# trigger for jobs that should not be created in merge requests +.non-merge-request-trigger: + extends: .base-trigger rules: - - if: $CI_PIPELINE_SOURCE == "schedule" + - if: $CI_PIPELINE_SOURCE != "merge_request_event" -################################### -# pipelines with different setups # +############################################# +# pipelines to be created in merge requests # full-dune-2.7-gcc: - extends: .default-trigger + extends: .base-trigger variables: IMAGE: $IMAGE_REGISTRY_URL/full:dune-2.7-gcc-ubuntu-20.04 minimal-dune-2.7-gcc: - extends: .default-trigger + extends: .base-trigger variables: IMAGE: $IMAGE_REGISTRY_URL/minimal:dune-2.7-gcc-ubuntu-20.04 full-dune-2.7-clang: - extends: .default-trigger + extends: .base-trigger variables: IMAGE: $IMAGE_REGISTRY_URL/full:dune-2.7-clang-ubuntu-20.04 ################################## # additional scheduled pipelines # full-dune-master-gcc: - extends: .scheduled-trigger + extends: .non-merge-request-trigger variables: IMAGE: $IMAGE_REGISTRY_URL/full:dune-master-gcc-ubuntu-20.04 full-dune-master-clang: - extends: .scheduled-trigger + extends: .non-merge-request-trigger variables: IMAGE: $IMAGE_REGISTRY_URL/full:dune-master-clang-ubuntu-20.04 -################################### -# triggers for downstream modules # -trigger lecture: - stage: trigger downstream modules - trigger: - project: dumux-repositories/dumux-lecture - # TODO: replace by master once development in lecture is finished - branch: feature/test-dumux-trigger - strategy: depend - variables: - DUMUX_BRANCH: $CI_COMMIT_BRANCH +# ################################### +# # triggers for downstream modules # +# trigger lecture: +# stage: trigger downstream modules +# trigger: +# project: dumux-repositories/dumux-lecture +# # TODO: replace by master once development in lecture is finished +# branch: feature/test-dumux-trigger +# strategy: depend +# variables: +# DUMUX_BRANCH: $CI_COMMIT_BRANCH -- GitLab From db3068f3f91c06f081502763184d874f400268c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dennis=20Gl=C3=A4ser?= Date: Tue, 13 Apr 2021 16:07:11 +0200 Subject: [PATCH 16/25] [ci] define creation rules in jobs --- .gitlab-ci.yml | 38 ++++++++++++++++++-------------- .gitlab-ci/makepipelineconfig.py | 3 ++- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 0418c45316..008eea11a8 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,36 +1,35 @@ stages: - - pipeline config - - test pipelines + - configure + - trigger # - downstream modules variables: IMAGE_REGISTRY_URL: $CI_REGISTRY/dumux-repositories/dumux-docker-ci +# Cases in which to create a pipeline. The `generate-config` job further +# specifies the situations in which they must be started manually. workflow: rules: - if: $CI_PIPELINE_SOURCE == "schedule" - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH - when: manual - if: $CI_PIPELINE_SOURCE == "merge_request_event" - when: manual -################################################################################### -# Stage 1: configure the test pipeline. # -# This creates the .yml to be used for the test pipeline trigger stage. Within # -# merge request, we create a .yml file that considers building and executing only # -# those test that are affected by the changes introduced in the merge request. # -# In all other cases, we use the default configuration which runs all tests. # -################################################################################### +################################################################################ +# Stage 1: configure the test pipeline. # +# This creates the .yml to be used for the test pipeline trigger stage. Within # +# merge request, we create a .yml file that adds a test selection stage before # +# the build stage to identify the tests affected by changes introduced in the # +# merge request. In all other cases, we use the default which runs all tests. # +################################################################################ generate-config: image: $IMAGE_REGISTRY_URL/full:dune-2.7-gcc-ubuntu-20.04 - stage: pipeline config + stage: configure script: - - dunecontrol --opts=$DUNE_OPTS_FILE --current all - | if [ $CI_PIPELINE_SOURCE == "merge_request_event" ]; then - cd build-cmake - python3 ../bin/testing/findtests.py -f affectedtests.json -t origin/master - python3 ../.gitlab-ci/makepipelineconfig.py -c affectedtests.json -o ../generated-config.yml + dunecontrol --opts=$DUNE_OPTS_FILE --current all + pushd build-cmake && python3 ../bin/testing/findtests.py -f affectedtests.json -t origin/master && popd + python3 .gitlab-ci/makepipelineconfig.py -c build-cmake/affectedtests.json -o generated-config.yml else python3 .gitlab-ci/makepipelineconfig.py -o generated-config.yml fi @@ -38,6 +37,11 @@ generate-config: paths: - generated-config.yml expire_in: 3 hours + rules: + - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH + when: manual + - if: $CI_PIPELINE_SOURCE == "merge_request_event" + when: manual ################################################################################### # Stage 2: trigger the test pipelines # @@ -49,7 +53,7 @@ generate-config: # basic trigger job to start the test pipeline .base-trigger: - stage: test pipelines + stage: trigger needs: - generate-config trigger: diff --git a/.gitlab-ci/makepipelineconfig.py b/.gitlab-ci/makepipelineconfig.py index 80b4598017..e1a3cf7bc1 100644 --- a/.gitlab-ci/makepipelineconfig.py +++ b/.gitlab-ci/makepipelineconfig.py @@ -63,7 +63,8 @@ with open(args['outfile'], 'w') as ymlFile: # we let the script create a small custom makeFile here on top of # `Makefile2`, where we define a new target to be built in parallel buildCommand = [ - 'rm TestMakefile', 'touch TestMakefile', + 'rm -f TestMakefile', + 'touch TestMakefile', 'echo "include CMakeFiles/Makefile2" >> TestMakefile', 'echo "" >> TestMakefile', 'echo "build_selected_tests: {}" >> TestMakefile' -- GitLab From ff6ef75886fc0087355e44473abc5191d0fde9f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dennis=20Gl=C3=A4ser?= Date: Tue, 13 Apr 2021 17:05:08 +0200 Subject: [PATCH 17/25] [ci] remove default yml use the generator script from the template instead --- .gitlab-ci/default.yml | 32 -------------------------------- 1 file changed, 32 deletions(-) delete mode 100644 .gitlab-ci/default.yml diff --git a/.gitlab-ci/default.yml b/.gitlab-ci/default.yml deleted file mode 100644 index 421c25ae5a..0000000000 --- a/.gitlab-ci/default.yml +++ /dev/null @@ -1,32 +0,0 @@ -default: - image: $IMAGE - -stages: - - build - - test - -workflow: - rules: - - if: $CI_PIPELINE_SOURCE=="parent_pipeline" - -build dumux: - stage: build - script: - - dunecontrol --opts=$DUNE_OPTS_FILE --current all - - dunecontrol --opts=$DUNE_OPTS_FILE --current make -k -j8 build_tests - artifacts: - paths: - - build-cmake - expire_in: 3 hours - -test dumux: - stage: test - script: - - cd build-cmake - - dune-ctest -j8 --no-tests=error - needs: - - job: build dumux - artifacts: true - artifacts: - reports: - junit: junit/dumux-cmake.xml -- GitLab From 8d2b768f57efdfa40ee6de2f30cec42cc2fcbd7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dennis=20Gl=C3=A4ser?= Date: Tue, 13 Apr 2021 18:10:22 +0200 Subject: [PATCH 18/25] [ci] escape colon in yml by --- .gitlab-ci/makepipelineconfig.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci/makepipelineconfig.py b/.gitlab-ci/makepipelineconfig.py index e1a3cf7bc1..fbe130910a 100644 --- a/.gitlab-ci/makepipelineconfig.py +++ b/.gitlab-ci/makepipelineconfig.py @@ -36,10 +36,11 @@ def substituteAndWrite(mapping): ymlFile.write(raw.substitute(**mapping)) +commandIndentation = ' '*args['indentation'] with open(args['outfile'], 'w') as ymlFile: def makeScriptString(commands): - commands = [' '*args['indentation'] + '- ' + comm for comm in commands] + commands = [commandIndentation + '- ' + comm for comm in commands] return '\n'.join(commands) # if no configuration is given, build and run all tests @@ -67,7 +68,9 @@ with open(args['outfile'], 'w') as ymlFile: 'touch TestMakefile', 'echo "include CMakeFiles/Makefile2" >> TestMakefile', 'echo "" >> TestMakefile', - 'echo "build_selected_tests: {}" >> TestMakefile' + '|\n' + + commandIndentation + + ' "echo "build_selected_tests: {}" >> TestMakefile"' .format(' '.join(targetNames)), 'make -j4 build_selected_tests'] testCommand = ['cd build-cmake', -- GitLab From 402056ff7717d75ade28d90c8f55cad7f7e25ff9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dennis=20Gl=C3=A4ser?= Date: Wed, 14 Apr 2021 08:50:43 +0200 Subject: [PATCH 19/25] [bin][findtest] add main file to test_files --- bin/testing/findtests.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/bin/testing/findtests.py b/bin/testing/findtests.py index daa006ac45..f92322c665 100755 --- a/bin/testing/findtests.py +++ b/bin/testing/findtests.py @@ -50,6 +50,7 @@ def isAffectedTest(testConfigFile, changed_files): cacheFile = "TestTargets/" + testConfig["target"] + ".json" command, dir = buildCommandAndDir(testConfig, cacheFile) + mainFile = command[-1] # detect headers included in this test # -MM skips headers from system directories @@ -65,8 +66,10 @@ def isAffectedTest(testConfigFile, changed_files): def isProjectHeader(headerPath): return projectDir in headerPath - test_files = set([os.path.relpath(header.lstrip(". "), projectDir) + test_files = [os.path.relpath(mainFile.lstrip(". "), projectDir)] + test_files.extend([os.path.relpath(header.lstrip(". "), projectDir) for header in filter(isProjectHeader, headers)]) + test_files = set(test_files) if hasCommonMember(changed_files, test_files): return True, testConfig["name"], testConfig["target"] -- GitLab From fd904f8a6df248102219e5307cf65471f5aa276f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dennis=20Gl=C3=A4ser?= Date: Wed, 14 Apr 2021 08:58:03 +0200 Subject: [PATCH 20/25] [ci][makeyml] support case of no tests --- .gitlab-ci/makepipelineconfig.py | 50 ++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/.gitlab-ci/makepipelineconfig.py b/.gitlab-ci/makepipelineconfig.py index fbe130910a..0dc3537452 100644 --- a/.gitlab-ci/makepipelineconfig.py +++ b/.gitlab-ci/makepipelineconfig.py @@ -37,6 +37,7 @@ def substituteAndWrite(mapping): commandIndentation = ' '*args['indentation'] +duneConfigCommand = 'dunecontrol --opts=$DUNE_OPTS_FILE --current all' with open(args['outfile'], 'w') as ymlFile: def makeScriptString(commands): @@ -45,7 +46,7 @@ with open(args['outfile'], 'w') as ymlFile: # if no configuration is given, build and run all tests if not args['testconfig']: - buildCommand = ['dunecontrol --opts=$DUNE_OPTS_FILE --current all', + buildCommand = [duneConfigCommand, 'dunecontrol --opts=$DUNE_OPTS_FILE --current ' 'make -k -j4 build_tests'] testCommand = ['cd build-cmake', 'dune-ctest -j4 --output-on-failure'] @@ -58,24 +59,35 @@ with open(args['outfile'], 'w') as ymlFile: testNames = config.keys() targetNames = [tc['target'] for tc in config.values()] - # The MakeFile generated by cmake contains .NOTPARALLEL statement, - # as it only allows one call to `CMakeFiles/Makefile2` at a time. - # Parallelism is taken care of within that latter Makefile. Thus, - # we let the script create a small custom makeFile here on top of - # `Makefile2`, where we define a new target to be built in parallel - buildCommand = [ - 'rm -f TestMakefile', - 'touch TestMakefile', - 'echo "include CMakeFiles/Makefile2" >> TestMakefile', - 'echo "" >> TestMakefile', - '|\n' - + commandIndentation - + ' "echo "build_selected_tests: {}" >> TestMakefile"' - .format(' '.join(targetNames)), - 'make -j4 build_selected_tests'] - testCommand = ['cd build-cmake', - 'dune-ctest -j4 --output-on-failure -R {}' - .format(' '.join(testNames))] + if not targetNames: + buildCommand = [duneConfigCommand, + 'echo "No tests to be built."'] + else: + # The MakeFile generated by cmake contains .NOTPARALLEL, + # as it only allows a single call to `CMakeFiles/Makefile2`. + # Parallelism is taken care of within that latter Makefile. + # We let the script create a small custom makeFile here on top + # of `Makefile2`, defining a new target to be built in parallel + buildCommand = [ + duneConfigCommand, + 'cd build-cmake', + 'rm -f TestMakefile && touch TestMakefile', + 'echo "include CMakeFiles/Makefile2" >> TestMakefile', + 'echo "" >> TestMakefile', + '|\n' + + commandIndentation + + ' echo "build_selected_tests: {}" >> TestMakefile' + .format(' '.join(targetNames)), + 'make -f TestMakefile -j4 build_selected_tests'] + + if not testNames: + testCommand = ['echo "No tests to be run, make empty report."', + 'cd build-cmake', + 'dune-ctest -R NOOP'] + else: + testCommand = ['cd build-cmake', + 'dune-ctest -j4 --output-on-failure -R {}' + .format(' '.join(testNames))] substituteAndWrite({'build_script': makeScriptString(buildCommand), 'test_script': makeScriptString(testCommand)}) -- GitLab From 6024776b2cfe9a54a422921eba0f37e14f8c6dad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dennis=20Gl=C3=A4ser?= Date: Wed, 14 Apr 2021 13:27:49 +0200 Subject: [PATCH 21/25] [ci][makeyml] use multiline command For a large number of tests, the resulting .yml could not be interpreted by the GitLab ci --- .gitlab-ci/makepipelineconfig.py | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/.gitlab-ci/makepipelineconfig.py b/.gitlab-ci/makepipelineconfig.py index 0dc3537452..14e7221a6e 100644 --- a/.gitlab-ci/makepipelineconfig.py +++ b/.gitlab-ci/makepipelineconfig.py @@ -44,6 +44,17 @@ with open(args['outfile'], 'w') as ymlFile: commands = [commandIndentation + '- ' + comm for comm in commands] return '\n'.join(commands) + def makeMultiLineCommand(commandParts): + + # add indentation to each part + result = [commandIndentation + ' ' + cp for cp in commandParts] + + # add line break token at the end of each part + result = ' \\\n'.join(result) + + # add multiline trigger token at the beginning + return '|\n' + result + # if no configuration is given, build and run all tests if not args['testconfig']: buildCommand = [duneConfigCommand, @@ -56,7 +67,7 @@ with open(args['outfile'], 'w') as ymlFile: with open(args['testconfig']) as configFile: config = json.load(configFile) - testNames = config.keys() + testNames = list(config.keys()) targetNames = [tc['target'] for tc in config.values()] if not targetNames: @@ -74,10 +85,9 @@ with open(args['outfile'], 'w') as ymlFile: 'rm -f TestMakefile && touch TestMakefile', 'echo "include CMakeFiles/Makefile2" >> TestMakefile', 'echo "" >> TestMakefile', - '|\n' - + commandIndentation - + ' echo "build_selected_tests: {}" >> TestMakefile' - .format(' '.join(targetNames)), + makeMultiLineCommand(['echo "build_selected_tests:"'] + + targetNames + + ['>> TestMakefile']), 'make -f TestMakefile -j4 build_selected_tests'] if not testNames: @@ -86,8 +96,10 @@ with open(args['outfile'], 'w') as ymlFile: 'dune-ctest -R NOOP'] else: testCommand = ['cd build-cmake', - 'dune-ctest -j4 --output-on-failure -R {}' - .format(' '.join(testNames))] + makeMultiLineCommand(['dune-ctest -j4 ' + '--output-on-failure ' + '-R'] + + testNames)] substituteAndWrite({'build_script': makeScriptString(buildCommand), 'test_script': makeScriptString(testCommand)}) -- GitLab From 43c45b3bdda7f5b41693e444a6fa8a582c7d3b30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dennis=20Gl=C3=A4ser?= Date: Wed, 14 Apr 2021 18:54:02 +0200 Subject: [PATCH 22/25] [ci] make test selection part of test pipeline --- .gitlab-ci.yml | 4 +- .gitlab-ci/default.yml.template | 6 +- .gitlab-ci/makepipelineconfig.py | 137 ++++++++++++++++--------------- bin/testing/runselectedtests.py | 0 4 files changed, 76 insertions(+), 71 deletions(-) mode change 100644 => 100755 bin/testing/runselectedtests.py diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 008eea11a8..a6587d0097 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -27,9 +27,7 @@ generate-config: script: - | if [ $CI_PIPELINE_SOURCE == "merge_request_event" ]; then - dunecontrol --opts=$DUNE_OPTS_FILE --current all - pushd build-cmake && python3 ../bin/testing/findtests.py -f affectedtests.json -t origin/master && popd - python3 .gitlab-ci/makepipelineconfig.py -c build-cmake/affectedtests.json -o generated-config.yml + python3 .gitlab-ci/makepipelineconfig.py -o generated-config.yml --affectedtestsonly else python3 .gitlab-ci/makepipelineconfig.py -o generated-config.yml fi diff --git a/.gitlab-ci/default.yml.template b/.gitlab-ci/default.yml.template index 29095ff05d..90135ea3f4 100644 --- a/.gitlab-ci/default.yml.template +++ b/.gitlab-ci/default.yml.template @@ -2,13 +2,14 @@ default: image: $$IMAGE stages: - - build - - test +${stages} workflow: rules: - if: $$CI_PIPELINE_SOURCE=="parent_pipeline" +${test_select_job} + build dumux: stage: build script: @@ -17,6 +18,7 @@ ${build_script} paths: - build-cmake expire_in: 3 hours +${build_needs} test dumux: stage: test diff --git a/.gitlab-ci/makepipelineconfig.py b/.gitlab-ci/makepipelineconfig.py index 14e7221a6e..d5ea63bb13 100644 --- a/.gitlab-ci/makepipelineconfig.py +++ b/.gitlab-ci/makepipelineconfig.py @@ -2,7 +2,6 @@ import os import sys -import json import string from argparse import ArgumentParser @@ -11,15 +10,22 @@ if sys.version_info.major < 3: sys.exit('Python 3 required') parser = ArgumentParser(description='Generate dumux test pipeline .yml file') -parser.add_argument('-o', '--outfile', required=True, +parser.add_argument('-o', '--outfile', + required=True, help='Specify the file to write the pipeline definition') -parser.add_argument('-c', '--testconfig', required=False, - help='Specify a test configuration file containing the ' - 'tests that should be run within the test pipeline') -parser.add_argument('-t', '--template', required=False, +parser.add_argument('-a', '--affectedtestsonly', + required=False, + action='store_true', + help='Use this flag to create a pipeline that runs only ' + 'those tests that are affected by changes w.r.t to ' + 'the origin/master branch') +parser.add_argument('-t', '--template', + required=False, default='.gitlab-ci/default.yml.template', help='Specify the template .yml file to be used') -parser.add_argument('-i', '--indentation', required=False, default=4, +parser.add_argument('-i', '--indentation', + required=False, + default=4, help='Specify the indentation for the script commands') args = vars(parser.parse_args()) @@ -37,69 +43,68 @@ def substituteAndWrite(mapping): commandIndentation = ' '*args['indentation'] -duneConfigCommand = 'dunecontrol --opts=$DUNE_OPTS_FILE --current all' with open(args['outfile'], 'w') as ymlFile: - def makeScriptString(commands): - commands = [commandIndentation + '- ' + comm for comm in commands] - return '\n'.join(commands) - - def makeMultiLineCommand(commandParts): + def wrapDuneControl(command): + return 'dunecontrol --opts=$DUNE_OPTS_FILE --current ' + command - # add indentation to each part - result = [commandIndentation + ' ' + cp for cp in commandParts] - - # add line break token at the end of each part - result = ' \\\n'.join(result) + def makeYamlList(commands, indent=commandIndentation): + commands = [indent + '- ' + comm for comm in commands] + return '\n'.join(commands) - # add multiline trigger token at the beginning - return '|\n' + result + # if no configuration is given, build and run all tests (skip select stage) + if not args['affectedtestsonly']: + buildCommand = [wrapDuneControl('all'), + wrapDuneControl('bexec make -k -j4 build_tests')] + testCommand = [wrapDuneControl('bexec dune-ctest' + ' -j4 --output-on-failure')] - # if no configuration is given, build and run all tests - if not args['testconfig']: - buildCommand = [duneConfigCommand, - 'dunecontrol --opts=$DUNE_OPTS_FILE --current ' - 'make -k -j4 build_tests'] - testCommand = ['cd build-cmake', 'dune-ctest -j4 --output-on-failure'] + substituteAndWrite({'build_script': makeYamlList(buildCommand), + 'test_script': makeYamlList(testCommand), + 'stages': makeYamlList(['build', 'test'], ' '), + 'test_select_job': '', + 'build_needs': ''}) - # otherwise, parse data from the given configuration file + # otherwise, add a stage that detects the tests to be run first else: - with open(args['testconfig']) as configFile: - config = json.load(configFile) - - testNames = list(config.keys()) - targetNames = [tc['target'] for tc in config.values()] - - if not targetNames: - buildCommand = [duneConfigCommand, - 'echo "No tests to be built."'] - else: - # The MakeFile generated by cmake contains .NOTPARALLEL, - # as it only allows a single call to `CMakeFiles/Makefile2`. - # Parallelism is taken care of within that latter Makefile. - # We let the script create a small custom makeFile here on top - # of `Makefile2`, defining a new target to be built in parallel - buildCommand = [ - duneConfigCommand, - 'cd build-cmake', - 'rm -f TestMakefile && touch TestMakefile', - 'echo "include CMakeFiles/Makefile2" >> TestMakefile', - 'echo "" >> TestMakefile', - makeMultiLineCommand(['echo "build_selected_tests:"'] - + targetNames - + ['>> TestMakefile']), - 'make -f TestMakefile -j4 build_selected_tests'] - - if not testNames: - testCommand = ['echo "No tests to be run, make empty report."', - 'cd build-cmake', - 'dune-ctest -R NOOP'] - else: - testCommand = ['cd build-cmake', - makeMultiLineCommand(['dune-ctest -j4 ' - '--output-on-failure ' - '-R'] - + testNames)] - - substituteAndWrite({'build_script': makeScriptString(buildCommand), - 'test_script': makeScriptString(testCommand)}) + selectStageName = 'configure' + selectJobName = 'select tests' + + stages = makeYamlList([selectStageName, 'build', 'test'], ' ') + buildNeeds = '\n'.join([' needs:', + ' - job: {}'.format(selectJobName), + ' artifacts: true']) + + selectJob = '\n'.join([selectJobName + ':', + ' stage: {}'.format(selectStageName), + ' script:']) + selectJob += '\n' + selectJob += makeYamlList([wrapDuneControl('all'), + 'pushd build-cmake', + 'python3 ../bin/testing/findtests.py' + ' -f ../affectedtests.json' + ' -t origin/master', + 'popd']) + selectJob += '\n' + selectJob += '\n'.join([' artifacts:', + ' paths:', + ' - affectedtests.json', + ' expire_in: 3 hours']) + + buildCommand = [wrapDuneControl('all'), + 'cp affectedtests.json build-cmake', + 'pushd build-cmake', + 'python3 ../bin/testing/runselectedtests.py ' + ' -c affectedtests.json -b', + 'popd'] + testCommand = [wrapDuneControl('all'), + 'pushd build-cmake', + 'python3 ../bin/testing/runselectedtests.py ' + ' -c affectedtests.json -t', + 'popd'] + + substituteAndWrite({'build_script': makeYamlList(buildCommand), + 'test_script': makeYamlList(testCommand), + 'stages': stages, + 'test_select_job': selectJob, + 'build_needs': buildNeeds}) diff --git a/bin/testing/runselectedtests.py b/bin/testing/runselectedtests.py old mode 100644 new mode 100755 -- GitLab From ee20fc79e70305976a7148c50081382f9c01840e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dennis=20Gl=C3=A4ser?= Date: Thu, 15 Apr 2021 21:37:46 +0200 Subject: [PATCH 23/25] [ci] avoid pipeline scripting --- .gitlab-ci.yml | 19 +++--- .gitlab-ci/affectedtestsonly.yml | 56 ++++++++++++++++ .gitlab-ci/default.yml | 31 +++++++++ .gitlab-ci/default.yml.template | 32 --------- .gitlab-ci/makepipelineconfig.py | 110 ------------------------------- 5 files changed, 97 insertions(+), 151 deletions(-) create mode 100644 .gitlab-ci/affectedtestsonly.yml create mode 100644 .gitlab-ci/default.yml delete mode 100644 .gitlab-ci/default.yml.template delete mode 100644 .gitlab-ci/makepipelineconfig.py diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index a6587d0097..6738553734 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -6,8 +6,9 @@ stages: variables: IMAGE_REGISTRY_URL: $CI_REGISTRY/dumux-repositories/dumux-docker-ci -# Cases in which to create a pipeline. The `generate-config` job further -# specifies the situations in which they must be started manually. +# Cases in which to create a pipeline. The `select-pipeline` job further +# specifies the situations in which they must be started manually. Currently, +# we only have automatic pipeline triggers for scheduled pipelines. workflow: rules: - if: $CI_PIPELINE_SOURCE == "schedule" @@ -21,19 +22,19 @@ workflow: # the build stage to identify the tests affected by changes introduced in the # # merge request. In all other cases, we use the default which runs all tests. # ################################################################################ -generate-config: +select-pipeline: image: $IMAGE_REGISTRY_URL/full:dune-2.7-gcc-ubuntu-20.04 stage: configure script: - | if [ $CI_PIPELINE_SOURCE == "merge_request_event" ]; then - python3 .gitlab-ci/makepipelineconfig.py -o generated-config.yml --affectedtestsonly + cp .gitlab-ci/affectedtestsonly.yml pipeline-config.yml else - python3 .gitlab-ci/makepipelineconfig.py -o generated-config.yml + cp .gitlab-ci/default.yml pipeline-config.yml fi artifacts: paths: - - generated-config.yml + - pipeline-config.yml expire_in: 3 hours rules: - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH @@ -53,11 +54,11 @@ generate-config: .base-trigger: stage: trigger needs: - - generate-config + - select-pipeline trigger: include: - - artifact: generated-config.yml - job: generate-config + - artifact: pipeline-config.yml + job: select-pipeline strategy: depend # trigger for jobs that should not be created in merge requests diff --git a/.gitlab-ci/affectedtestsonly.yml b/.gitlab-ci/affectedtestsonly.yml new file mode 100644 index 0000000000..c3bb83411d --- /dev/null +++ b/.gitlab-ci/affectedtestsonly.yml @@ -0,0 +1,56 @@ +default: + image: $IMAGE + +stages: + - configure + - build + - test + +workflow: + rules: + - if: $CI_PIPELINE_SOURCE=="parent_pipeline" + +select tests: + stage: configure + script: + - dunecontrol --opts=$DUNE_OPTS_FILE --current all + - | + pushd build-cmake + python3 ../bin/testing/findtests.py -f ../affectedtests.json -t origin/master + popd + artifacts: + paths: + - affectedtests.json + expire_in: 3 hours + +build dumux: + stage: build + script: + - dunecontrol --opts=$DUNE_OPTS_FILE --current all + - cp affectedtests.json build-cmake + - | + pushd build-cmake + python3 ../bin/testing/runselectedtests.py -c affectedtests.json -b + popd + artifacts: + paths: + - build-cmake + expire_in: 3 hours + needs: + - job: select tests + artifacts: true + +test dumux: + stage: test + script: + - dunecontrol --opts=$DUNE_OPTS_FILE --current all + - | + pushd build-cmake + python3 ../bin/testing/runselectedtests.py -c affectedtests.json -t + popd + needs: + - job: build dumux + artifacts: true + artifacts: + reports: + junit: junit/dumux-cmake.xml diff --git a/.gitlab-ci/default.yml b/.gitlab-ci/default.yml new file mode 100644 index 0000000000..2293458b02 --- /dev/null +++ b/.gitlab-ci/default.yml @@ -0,0 +1,31 @@ +default: + image: $IMAGE + +stages: + - build + - test + +workflow: + rules: + - if: $CI_PIPELINE_SOURCE=="parent_pipeline" + +build dumux: + stage: build + script: + - dunecontrol --opts=$DUNE_OPTS_FILE --current all + - dunecontrol --opts=$DUNE_OPTS_FILE --current bexec make -k -j4 build_tests + artifacts: + paths: + - build-cmake + expire_in: 3 hours + +test dumux: + stage: test + script: + - dunecontrol --opts=$DUNE_OPTS_FILE --current bexec dune-ctest -j4 --output-on-failure + needs: + - job: build dumux + artifacts: true + artifacts: + reports: + junit: junit/dumux-cmake.xml diff --git a/.gitlab-ci/default.yml.template b/.gitlab-ci/default.yml.template deleted file mode 100644 index 90135ea3f4..0000000000 --- a/.gitlab-ci/default.yml.template +++ /dev/null @@ -1,32 +0,0 @@ -default: - image: $$IMAGE - -stages: -${stages} - -workflow: - rules: - - if: $$CI_PIPELINE_SOURCE=="parent_pipeline" - -${test_select_job} - -build dumux: - stage: build - script: -${build_script} - artifacts: - paths: - - build-cmake - expire_in: 3 hours -${build_needs} - -test dumux: - stage: test - script: -${test_script} - needs: - - job: build dumux - artifacts: true - artifacts: - reports: - junit: junit/dumux-cmake.xml diff --git a/.gitlab-ci/makepipelineconfig.py b/.gitlab-ci/makepipelineconfig.py deleted file mode 100644 index d5ea63bb13..0000000000 --- a/.gitlab-ci/makepipelineconfig.py +++ /dev/null @@ -1,110 +0,0 @@ -#!/usr/bin/env python3 - -import os -import sys -import string -from argparse import ArgumentParser - -# require Python 3 -if sys.version_info.major < 3: - sys.exit('Python 3 required') - -parser = ArgumentParser(description='Generate dumux test pipeline .yml file') -parser.add_argument('-o', '--outfile', - required=True, - help='Specify the file to write the pipeline definition') -parser.add_argument('-a', '--affectedtestsonly', - required=False, - action='store_true', - help='Use this flag to create a pipeline that runs only ' - 'those tests that are affected by changes w.r.t to ' - 'the origin/master branch') -parser.add_argument('-t', '--template', - required=False, - default='.gitlab-ci/default.yml.template', - help='Specify the template .yml file to be used') -parser.add_argument('-i', '--indentation', - required=False, - default=4, - help='Specify the indentation for the script commands') -args = vars(parser.parse_args()) - - -# substitute content from template and write to target -def substituteAndWrite(mapping): - - template = args['template'] - if not os.path.exists(template): - sys.exit("Template file '" + template + "' could not be found") - - with open(args['outfile'], 'w') as ymlFile: - raw = string.Template(open(template).read()) - ymlFile.write(raw.substitute(**mapping)) - - -commandIndentation = ' '*args['indentation'] -with open(args['outfile'], 'w') as ymlFile: - - def wrapDuneControl(command): - return 'dunecontrol --opts=$DUNE_OPTS_FILE --current ' + command - - def makeYamlList(commands, indent=commandIndentation): - commands = [indent + '- ' + comm for comm in commands] - return '\n'.join(commands) - - # if no configuration is given, build and run all tests (skip select stage) - if not args['affectedtestsonly']: - buildCommand = [wrapDuneControl('all'), - wrapDuneControl('bexec make -k -j4 build_tests')] - testCommand = [wrapDuneControl('bexec dune-ctest' - ' -j4 --output-on-failure')] - - substituteAndWrite({'build_script': makeYamlList(buildCommand), - 'test_script': makeYamlList(testCommand), - 'stages': makeYamlList(['build', 'test'], ' '), - 'test_select_job': '', - 'build_needs': ''}) - - # otherwise, add a stage that detects the tests to be run first - else: - selectStageName = 'configure' - selectJobName = 'select tests' - - stages = makeYamlList([selectStageName, 'build', 'test'], ' ') - buildNeeds = '\n'.join([' needs:', - ' - job: {}'.format(selectJobName), - ' artifacts: true']) - - selectJob = '\n'.join([selectJobName + ':', - ' stage: {}'.format(selectStageName), - ' script:']) - selectJob += '\n' - selectJob += makeYamlList([wrapDuneControl('all'), - 'pushd build-cmake', - 'python3 ../bin/testing/findtests.py' - ' -f ../affectedtests.json' - ' -t origin/master', - 'popd']) - selectJob += '\n' - selectJob += '\n'.join([' artifacts:', - ' paths:', - ' - affectedtests.json', - ' expire_in: 3 hours']) - - buildCommand = [wrapDuneControl('all'), - 'cp affectedtests.json build-cmake', - 'pushd build-cmake', - 'python3 ../bin/testing/runselectedtests.py ' - ' -c affectedtests.json -b', - 'popd'] - testCommand = [wrapDuneControl('all'), - 'pushd build-cmake', - 'python3 ../bin/testing/runselectedtests.py ' - ' -c affectedtests.json -t', - 'popd'] - - substituteAndWrite({'build_script': makeYamlList(buildCommand), - 'test_script': makeYamlList(testCommand), - 'stages': stages, - 'test_select_job': selectJob, - 'build_needs': buildNeeds}) -- GitLab From cba97a425157c90f434c01ba66161ab87b4cc274 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dennis=20Gl=C3=A4ser?= Date: Fri, 16 Apr 2021 14:45:50 +0200 Subject: [PATCH 24/25] [ci] enable lecture trigger --- .gitlab-ci.yml | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6738553734..e53b44de6a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,7 +1,7 @@ stages: - configure - trigger - # - downstream modules + - downstream modules variables: IMAGE_REGISTRY_URL: $CI_REGISTRY/dumux-repositories/dumux-docker-ci @@ -15,6 +15,7 @@ workflow: - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH - if: $CI_PIPELINE_SOURCE == "merge_request_event" + ################################################################################ # Stage 1: configure the test pipeline. # # This creates the .yml to be used for the test pipeline trigger stage. Within # @@ -42,8 +43,9 @@ select-pipeline: - if: $CI_PIPELINE_SOURCE == "merge_request_event" when: manual + ################################################################################### -# Stage 2: trigger the test pipelines # +# Stage 2: trigger the Dumux test pipelines # # In this stage, we trigger the test pipeline with different configurations, i.e. # # different Dune versions, compilers, etc. Within merge requests, we create three # # test pipelines including two different compilers and a full and minimal setup # @@ -62,7 +64,7 @@ select-pipeline: strategy: depend # trigger for jobs that should not be created in merge requests -.non-merge-request-trigger: +.non-mr-trigger: extends: .base-trigger rules: - if: $CI_PIPELINE_SOURCE != "merge_request_event" @@ -87,23 +89,27 @@ full-dune-2.7-clang: ################################## # additional scheduled pipelines # full-dune-master-gcc: - extends: .non-merge-request-trigger + extends: .non-mr-trigger variables: IMAGE: $IMAGE_REGISTRY_URL/full:dune-master-gcc-ubuntu-20.04 full-dune-master-clang: - extends: .non-merge-request-trigger + extends: .non-mr-trigger variables: IMAGE: $IMAGE_REGISTRY_URL/full:dune-master-clang-ubuntu-20.04 -# ################################### -# # triggers for downstream modules # -# trigger lecture: -# stage: trigger downstream modules -# trigger: -# project: dumux-repositories/dumux-lecture -# # TODO: replace by master once development in lecture is finished -# branch: feature/test-dumux-trigger -# strategy: depend -# variables: -# DUMUX_BRANCH: $CI_COMMIT_BRANCH + +######################################################### +# Stage 3: trigger test pipelines of downstream modules # +######################################################### + +# trigger lecture test +trigger lecture: + stage: downstream modules + trigger: + project: dumux-repositories/dumux-lecture + # TODO: use master when lecture pipeline is set up + branch: feature/test-dumux-trigger + strategy: depend + variables: + DUMUX_MERGE_REQUEST_BRANCH: $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME -- GitLab From 53bba82c2fe578f97ca833ec890be6f36ccad10a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dennis=20Gl=C3=A4ser?= Date: Wed, 28 Apr 2021 11:33:13 +0200 Subject: [PATCH 25/25] [ci] avoid call to dune control in test stage --- .gitlab-ci/affectedtestsonly.yml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/.gitlab-ci/affectedtestsonly.yml b/.gitlab-ci/affectedtestsonly.yml index c3bb83411d..7387f722f4 100644 --- a/.gitlab-ci/affectedtestsonly.yml +++ b/.gitlab-ci/affectedtestsonly.yml @@ -16,20 +16,19 @@ select tests: - dunecontrol --opts=$DUNE_OPTS_FILE --current all - | pushd build-cmake - python3 ../bin/testing/findtests.py -f ../affectedtests.json -t origin/master + python3 ../bin/testing/findtests.py -f affectedtests.json -t origin/master popd artifacts: paths: - - affectedtests.json + - build-cmake expire_in: 3 hours build dumux: stage: build script: - - dunecontrol --opts=$DUNE_OPTS_FILE --current all - - cp affectedtests.json build-cmake - | pushd build-cmake + make clean python3 ../bin/testing/runselectedtests.py -c affectedtests.json -b popd artifacts: @@ -43,7 +42,6 @@ build dumux: test dumux: stage: test script: - - dunecontrol --opts=$DUNE_OPTS_FILE --current all - | pushd build-cmake python3 ../bin/testing/runselectedtests.py -c affectedtests.json -t -- GitLab