diff --git a/.ci/hpc-workflows b/.ci/hpc-workflows index 043a4b6711..97ca807b0e 160000 --- a/.ci/hpc-workflows +++ b/.ci/hpc-workflows @@ -1 +1 @@ -Subproject commit 043a4b6711e7f7d6dd41bd932e6e7336334e9a53 +Subproject commit 97ca807b0e1b7d67a35ab10e938b29774242e48e diff --git a/.ci/tests/build.sh b/.ci/tests/build.sh index a0598fd499..135a751ca1 100755 --- a/.ci/tests/build.sh +++ b/.ci/tests/build.sh @@ -3,7 +3,7 @@ help() { echo "./build.sh as_host workingdir [options] [-- ]" echo " as_host First argument must be the host configuration to use for environment loading" - echo " workingdir First argument must be the working dir to immediate cd to" + echo " workingdir Second argument must be the working dir to immediate cd to" echo " -c Configuration build type, piped directly into configure" echo " -n Configuration nesting type, piped directly into configure" echo " -o Configuration optstring passed into configure" diff --git a/.ci/tests/runNamelists.sh b/.ci/tests/runNamelists.sh new file mode 100755 index 0000000000..797e6542dd --- /dev/null +++ b/.ci/tests/runNamelists.sh @@ -0,0 +1,392 @@ +#!/bin/sh +help() +{ + echo "./runNamelists.sh [workingdir] [options] [-- ]" + echo " as_host First argument must be the host configuration to use for environment loading" + echo " workingdir Second argument must be the working dir to immediate cd to" + echo " -c Directory for specific core built" + echo " -r Directory to run in using mkdir and symlinking -c for each namelist" + echo " -b Binary executable for WRF front-end (ideal/real/etc.)" + echo " -f Namelist folder to look for namelists under" + echo " -n Comma-delimited list of namelists to test, each of which will in serial be run by replacing namelist.input" + echo " -d Data directory to link into run directory" + echo " -p Parallel launch command (MPI), e.g. mpirun, mpiexec_mpt, mpiexec -np 8 --oversubscribe" + echo " -k diffwrf command binary path, if not set will use external/io_netcdf/diffwrf" + echo " -s Save result data to prefix location, full path for run constructed as /// " + echo " -i Folder for bitwise-identical results, full path for run constructed as /// " + echo " -e environment variables in comma-delimited list, e.g. var=1,foo,bar=0" + echo " -- Directly pass options to hostenv.sh, equivalent to hostenv.sh " + echo " -h Print this message" + echo "" + echo "If you wish to use an env var in your arg such as '-c \$SERIAL -e SERIAL=32', you must" + echo "you will need to do '-c \\\$SERIAL -e SERIAL=32' to delay shell expansion when input from shell/CLI" + echo "" + echo "If -i is provided, bitwise-identical checks are performed as part of checks" +} + +echo "Input arguments:" +echo "$*" + +AS_HOST=$1 +shift +if [ $AS_HOST = "-h" ]; then + help + exit 0 +fi + +workingDirectory=$1 +shift + +cd $workingDirectory + +# Get some helper functions +. .ci/env/helpers.sh + +while getopts c:r:b:f:n:d:p:k:s:i:e:h opt; do + case $opt in + c) + coreDir="$OPTARG" + ;; + r) + runDir="$OPTARG" + ;; + b) + binFirst="$OPTARG" + ;; + f) + namelistFolder="$OPTARG" + ;; + n) + namelists="$OPTARG" + ;; + d) + data="$OPTARG" + ;; + p) + parallelExec="$OPTARG" + ;; + k) + diffExec="$OPTARG" + ;; + s) + moveFolder="$OPTARG" + ;; + i) + identicalFolder="$OPTARG" + ;; + e) + envVars="$envVars,$OPTARG" + ;; + h) help; exit 0 ;; + *) help; exit 1 ;; + :) help; exit 1 ;; + \?) help; exit 1 ;; + esac +done + +shift "$((OPTIND - 1))" + +# Everything else goes to our env setup +. .ci/env/hostenv.sh $* + +# Now evaluate env vars in case it pulls from hostenv.sh +if [ ! -z $envVars ]; then + setenvStr "$envVars" +fi + +# Re-evaluate input values for delayed expansion +eval "coreDir=\$( realpath \"$coreDir\" )" +eval "namelistFolder=\$( realpath \"$namelistFolder\" )" +eval "namelists=\"$namelists\"" +eval "data=\$( realpath \"$data\" )" +eval "parallelExec=\"$parallelExec\"" +eval "moveFolder=\"$moveFolder\"" +eval "identicalFolder=\"$identicalFolder\"" + +eval "runDir=\"$runDir\"" +mkdir -p $runDir +# Now set to realpath since it exists +runDir=$( realpath $runDir ) + +# And prep so other values can be derived +ln -sf $coreDir/* $runDir/ + +eval "binFirst=\$( realpath \"$runDir/$binFirst\" )" + + +wrf=$( realpath $( find $runDir -type f -name wrf -o -name wrf.exe | head -n 1 ) ) +rd_12_norm=$( realpath .ci/tests/SCRIPTS/rd_l2_norm.py ) + +# Check our paths +if [ ! -x "${wrf}" ]; then + echo "No wrf executable found" + exit 1 +fi + +if [ ! -x "${binFirst}" ]; then + echo "No domain preparation executable found" + exit 1 +fi + +if [ ! -d "${data}" ]; then + echo "No valid data path provided" + exit 1 +fi + +if [ ! -d "${namelistFolder}" ]; then + echo "No valid namelist folder provided" + exit 1 +fi + +if [ -z "${diffExec}" ]; then + diffExec=$( realpath $workingDirectory/external/io_netcdf/diffwrf ) +else + eval "diffExec=\$( realpath \"$diffExec\" )" +fi + + + + +################################################################################ +# +# Things done only once +# Go to core dir to make sure it exists +cd $coreDir || exit $? +# Clean up previous runs +rm wrfinput_d* wrfbdy_d* wrfout_d* wrfchemi_d* wrf_chem_input_d* rsl* real.print.out* wrf.print.out* wrf_d0*_runstats.out qr_acr_qg_V4.dat fort.98 fort.88 -rf + + +# Go to run location now - We only operate here from now on +cd $runDir || exit $? +# Clean up previous runs +rm wrfinput_d* wrfbdy_d* wrfout_d* wrfchemi_d* wrf_chem_input_d* rsl* real.print.out* wrf.print.out* wrf_d0*_runstats.out qr_acr_qg_V4.dat fort.98 fort.88 -rf + +# Link in data in here +ln -sf $data/* . + +# +################################################################################ + + +################################################################################ +# +# Loop testing namelists +tmpIFS=$IFS +IFS="," + +# Since we might fail or succeed on certain namelists, make a running set of failures +errorMsg="" + +for namelist in $namelists; do + banner 42 "START $namelist" + + parallelExecToUse="$parallelExec" + #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + # SPECIFIC TO NESTED DOMAINS - WE MUST RUN AN ODD NUMBER OF MPI TASKS + # THIS IS NOTED BY THE NAMELIST HAVING 'NE' OR 'VN' AT THE END + #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + if [ -n "$parallelExec" ] && { [ $( echo $namelist | grep -Ec "NE$" ) -eq 1 ] || [ $( echo $namelist | grep -Ec "VN$" ) -eq 1 ]; } then + # Check if parallel exec np is even and if so, reduce by 1 + parallelExecSplit=$( echo "$parallelExec" | sed -e "s/\(.*\?-np[ ]*\)\([0-9]\+\)\(.*\?\)/\1;\2;\3/g" ) + partFront=$( echo "$parallelExecSplit" | awk -F';' '{print $1}' ) + partEnd=$( echo "$parallelExecSplit" | awk -F';' '{print $3}' ) + numProcs=$( echo "$parallelExecSplit" | awk -F';' '{print $2}' ) + if [ $(( $numProcs % 2 )) -eq 0 ]; then + echo "MPI runs with nested namelist domains require odd-number tasks, reducing by one" + numProcs=$(( $numProcs - 1 )) + parallelExecToUse="$partFront$numProcs$partEnd" + parallelExecToUseBinFirst="$partFront$numProcs$partEnd" + echo "New command will be '$parallelExecToUse'" + fi + + # Check if we are runnng ideal + if [ $( contains $binFirst "ideal" ) -eq 0 ]; then + echo "Ideal test case initial conditions must be generated with one MPI rank at most" + parallelExecToUseBinFirst="$partFront"1"$partEnd" + fi + fi + + + # Clean up output of any of these runs + rm wrfinput_d* wrfbdy_d* wrfout_d* rsl* real.print.out* wrf.print.out* wrf_d0*_runstats.out qr_acr_qg_V4.dat fort.98 fort.88 -rf + + # Copy namelist + echo "Setting $namelistFolder/$namelist as namelist.input" + # remove old namelist.input which may be a symlink in which case this would have failed + rm namelist.input + cp $namelistFolder/$namelist namelist.input || exit $? + + # Run setup + + echo "Running $parallelExecToUseBinFirst $binFirst" + + eval "$parallelExecToUseBinFirst $binFirst | tee setup.print.out" + result=$? + if [ -n "$parallelExecToUseBinFirst" ]; then + if [ $( ls ./rsl.out.* 2>/dev/null | wc -l ) -ne 0 ]; then + # Output the rsl. output + cat $( ls ./rsl.out.* | sort | head -n 1 ) + fi + fi + + if [ $result -ne 0 ]; then + currentErrorMsg="[$namelist] $parallelExecToUseBinFirst $binFirst failed" + echo "$currentErrorMsg" + errorMsg="$errorMsg\n$currentErrorMsg" + continue + fi + + # run wrf + echo "Running $parallelExecToUse $wrf" + + eval "$parallelExecToUse $wrf | tee wrf.print.out" + result=$? + if [ -n "$parallelExecToUse" ]; then + if [ $( ls ./rsl.out.* 2>/dev/null | wc -l ) -ne 0 ]; then + # Output the rsl. output + cat $( ls ./rsl.out.* | sort | head -n 1 ) + fi + fi + + + + if [ $result -ne 0 ]; then + currentErrorMsg="[$namelist] $parallelExecToUse $wrf failed" + echo "$currentErrorMsg" + errorMsg="$errorMsg\n$currentErrorMsg" + continue + fi + + # Check output per domain + maxDom=$( grep max_dom namelist.input | awk '{print $3}' | tr -d ',' ) + currentDom=0 + while [ $currentDom -lt $maxDom ]; do + currentDom=$(( $currentDom + 1 )) + + domFiles=$( ls -1 | grep wrfout_d0${currentDom} | wc -l | awk '{print $1}' ) + + if [ $domFiles -eq 0 ]; then + currentErrorMsg="[$namelist] No output files generated for domain $currentDom" + echo "$currentErrorMsg" + errorMsg="$errorMsg\n$currentErrorMsg" + continue + fi + + ncdump wrfout_d0${currentDom}_* | grep -i nan | grep -vi dominant + okNan=$? + timeSteps=$( ncdump -h wrfout_d0${currentDom}_* | grep "Time = UNLIMITED" | cut -d"(" -f2 | awk '{print $1}' ) + + if [ $okNan -eq 1 ] && [ $timeSteps -eq 2 ]; then + # Super ok, store output in file for comparison later + python3 $rd_12_norm wrfout_d0${currentDom}_* > wrf_d0${currentDom}_runstats.out + else + # Super NOT ok + currentErrorMsg="[$namelist] Checks on output failed. okNan=$okNan, timeSteps=$timeSteps when expected okNan=1 && timeSteps=2" + echo "$currentErrorMsg" + errorMsg="$errorMsg\n$currentErrorMsg" + continue + fi + done + + # try comp + if [ ! -z $identicalFolder ]; then + if [ -d $workingDirectory/$identicalFolder/$namelist/ ]; then + echo "Comparing current $namelist output to output stored in $workingDirectory/$identicalFolder/$namelist/" + + for io_type in input out; do + for dom in d01 d02 d03; do + if [ -e $workingDirectory/$identicalFolder/$namelist/wrf${io_type}_${dom}* ]; then + if [ ! -e ./wrf${io_type}_${dom}* ]; then + # Domain does not exist in our current run but in the provided folder, that should not happen -FAIL! + currentErrorMsg="[$namelist] Domain $( ls wrf${io_type}_${dom}* ) file $dom exists in $workingDirectory/$identicalFolder/$namelist but not in this run, cannot compare results" + echo "$currentErrorMsg" + errorMsg="$errorMsg\n$currentErrorMsg" + continue + fi + + # We have a domain to check - should exist in both (we are treating the identical folder as truth) + if [ "${io_type}" = "out" ]; then + diff $workingDirectory/$identicalFolder/$namelist/wrf_${dom}_runstats.out $(pwd)/wrf_${dom}_runstats.out + statDiff=$? + fi + + $diffExec $workingDirectory/$identicalFolder/$namelist/wrf${io_type}_${dom}* wrf${io_type}_${dom}* + result=$? + + if [ $result -ne 0 ]; then + currentErrorMsg="[$namelist] $diffExec failed" + echo "$currentErrorMsg" + errorMsg="$errorMsg\n$currentErrorMsg" + continue + fi + + if [ -e fort.98 ] || [ -e fort.88 ]; then + currentErrorMsg="[$namelist] $( ls $workingDirectory/$identicalFolder/$namelist/wrf${io_type}_${dom}* ) and current wrf${io_type}_${dom}* differ" + if [ -n "$statDiff" ] && [ $statDiff -eq 0 ]; then + currentErrorMsg="$currentErrorMsg - but are statistically equivalent based on checksum" + fi + echo "$currentErrorMsg" + cat fort.98 fort.88 2>/dev/null + errorMsg="$errorMsg\n$currentErrorMsg" + continue + fi + elif [ -e ./wrf${io_type}_${dom}* ]; then + echo "Domain file $( ls wrf${io_type}_${dom}* ) exists in $( pwd ) but not in $workingDirectory/$identicalFolder/$namelist/, is this an error?" + else + # neither has it, skip + echo "Domain file wrf${io_type}_${dom}* not generated for namelist $namelist, skipping check" + fi + done + done + else + echo "No output to check in $workingDirectory/$identicalFolder for $namelist" + fi + fi + + # Now if we have a move folder, do that + if [ ! -z $moveFolder ]; then + mkdir -p $workingDirectory/$moveFolder/$namelist/ + + # we are in core dir, find our output + echo "Moving output files to $workingDirectory/$moveFolder/$namelist/" + find . -type f -name "wrfinput_d*" \ + -o -name "wrfbdy_d*" \ + -o -name "wrfout_d*" \ + -o -name "wrfchemi_d*" \ + -o -name "wrf_chem_input_d*" \ + -o -name "rsl*" \ + -o -name "setup.print.out*" \ + -o -name "wrf.print.out*" \ + -o -name "wrf_d0*_runstats.out" + # Now move + find . -type f \( -name "wrfinput_d*" \ + -o -name "wrfbdy_d*" \ + -o -name "wrfout_d*" \ + -o -name "wrfchemi_d*" \ + -o -name "wrf_chem_input_d*" \ + -o -name "rsl*" \ + -o -name "setup.print.out*" \ + -o -name "wrf.print.out*" \ + -o -name "wrf_d0*_runstats.out" \) \ + -exec mv {} $workingDirectory/$moveFolder/$namelist/ \; + fi + + banner 42 "STOP $namelist" +done +IFS=$tmpIFS + +# If we passed, clean up after ourselves +if [ -z "$errorMsg" ]; then + # Unlink everything we linked in + ls $data/ | xargs -I{} rm {} + + # Clean up once more since we passed + rm -rf wrfinput_d* wrfbdy_d* wrfout_d* wrfchemi_d* wrf_chem_input_d* rsl* setup.print.out* wrf.print.out* qr_acr_qg_V4.dat fort.98 fort.88 + + # We passed! + echo "TEST $(basename $0) PASS" +else + printf "%b" "$errorMsg" + exit 1 +fi + diff --git a/.ci/wrf_em_real_tests.jsonc b/.ci/wrf_em_real_tests.jsonc new file mode 100644 index 0000000000..88dc9d81f7 --- /dev/null +++ b/.ci/wrf_em_real_tests.jsonc @@ -0,0 +1,861 @@ +// Tests emulating the code that is generated and run from +// https://github.com/kkeene44/wrf-coop/blob/version16_update/build.csh +// and +// https://github.com/wrf-model/SCRIPTS/blob/master/script.csh +{ + "submit_options" : + { + "timelimit" : "00:10:00", + "working_directory" : "..", + "arguments" : + { + ".*build.*::base_env_numprocs" : [ "-e", "NUM_PROCS=4" ], + ".*testcase.*::base_env_numprocs" : [ "-e", "NUM_PROCS=4" ], + + ".*build.*::args_nesting" : [ "-n", "1" ], + ".*build.*::args_configopt" : [ "-o", "-d" ], + ".*build.*::args_build_tgt" : [ "-b", "em_real -j $NUM_PROCS" ], + + ".*build-serial::args_config": [ "-c", "32" ], + ".*build-omp::args_config" : [ "-c", "33" ], + ".*build-mpi::args_config" : [ "-c", "34" ], + + ".*testcase.*::global_env" : [ "-e", "DATA=/path/to/data" ], + ".*testcase.*::args_always" : [ "-c", "test/em_real", "-b", "real.exe", "-d", "$DATA/em_real" ], + ".*testcase-mpi.*::exec_mpi" : [ "-p", "mpirun -np $NUM_PROCS" ], + ".*testcase-omp.*::env" : [ "-e", "OMP_NUM_THREADS=$NUM_PROCS" ], + + ".*testcase.*::args_namelist_dir" : [ "-r", "runNamelists/$NAMELIST_DIR" ], + + ".*testcase-serial.*::dir" : [ "-f", ".ci/tests/SCRIPTS/Namelists/weekly/$NAMELIST_DIR/SERIAL/", "-s", "serial_results/$NAMELIST_DIR" ], + ".*testcase-omp.*::dir" : [ "-f", ".ci/tests/SCRIPTS/Namelists/weekly/$NAMELIST_DIR/OPENMP/", "-i", "serial_results/$NAMELIST_DIR" ], + ".*testcase-mpi.*::dir" : [ "-f", ".ci/tests/SCRIPTS/Namelists/weekly/$NAMELIST_DIR/MPI/", "-i", "serial_results/$NAMELIST_DIR" ] + }, + // This is an example of how one might set up the environment to run locally + "mmm-mystic" : + { + "submission" : "LOCAL", + "arguments" : + { + ".*build.*::base_env_numprocs" : [ "-e", "NUM_PROCS=10" ], + ".*testcase.*::base_env_numprocs" : [ "-e", "NUM_PROCS=10" ], + ".*::first_global_env" : [ "-e", "NETCDF=$HOME/dependencies/netcdf_for_wrf" ], + ".*testcase.*::global_env" : + [ + "-e", "DATA=$HOME/wrf-model/DATA/namelists/Data/", + "-e", "LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$NETCDF/lib" + ], + ".*mpi.*::path" : [ "-e", "PATH=$PATH:$HOME/dependencies/mpich/bin" ] + } + }, + "hsn.de.hpc" : + { + "submission" : "PBS", + "queue" : "main", + "hpc_arguments" : + { + ".*testcase-serial.*::node_select" : + { + "-l " : { "select" : 1, "ncpus" : 1 } + }, + // for any test case that isn't serial apply the following + "^((?!testcase-serial).)*$::node_select" : + { + "-l " : { "select" : 1, "ncpus" : 10, + // Only apply this to MPI tests + ".*testcase-mpi.*::mpiprocs" : 10, + // only for OMP tests + ".*testcase-omp.*::ompthreads" : 10 } + }, + "priority" : { "-l " : { "job_priority" : "economy" } } + }, + "arguments" : + { + // These need to be representative of the resources we've requested + ".*build.*::base_env_numprocs" : [ "-e", "NUM_PROCS=10" ], + ".*testcase.*::base_env_numprocs" : [ "-e", "NUM_PROCS=10" ], + ".*testcase.*::global_env" : + [ + "-e", "DATA=/glade/work/aislas/github/data/wrf/regtest/Data/", + "-e", "LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$NETCDF/lib:$NETCDF/lib64" + ], + "global_modules" : [ "gcc", "netcdf" ], + ".*mpi.*::mpi_module" : [ "cray-mpich" ] + } + } + }, + "em_real" : + { + "submit_options" : + { + "arguments" : + { + // Remove auto-filled dir and supply sub-testcase specific ones + ".*testcase.*::args_namelist_dir" : [ ], + ".*testcase.*0.*::args_namelist" : + [ + "-n", "namelist.input.3dtke", + "-e", "NAMELIST_DIR=em_real", + "-r", "runNamelists/$NAMELIST_DIR/0" + ], + ".*testcase.*1.*::args_namelist" : + [ + "-n", "namelist.input.conus", + "-e", "NAMELIST_DIR=em_real", + "-r", "runNamelists/$NAMELIST_DIR/1" + ], + // This is producing inconsistent bitwise identical results + // ".*testcase.*2.*::args_namelist" : + // [ + // "-n", "namelist.input.rap", + // "-e", "NAMELIST_DIR=em_real", + // "-r", "runNamelists/$NAMELIST_DIR/2" + // ], + ".*testcase.*3.*::args_namelist" : + [ + "-n", "namelist.input.tropical", + "-e", "NAMELIST_DIR=em_real", + "-r", "runNamelists/$NAMELIST_DIR/3" + ] + } + }, + "steps" : + { + "build-serial" : + { + "command" : ".ci/tests/build.sh" + }, + "testcase-serial0" : + { + "submit_options" : { "timelimit" : "00:40:00" }, + "command" : ".ci/tests/runNamelists.sh", + "dependencies" : { "build-serial" : "afterok" } + }, + "testcase-serial1" : + { + "submit_options" : { "timelimit" : "00:40:00" }, + "command" : ".ci/tests/runNamelists.sh", + "dependencies" : { "build-serial" : "afterok" } + }, + // "testcase-serial2" : + // { + // "submit_options" : { "timelimit" : "00:40:00" }, + // "command" : ".ci/tests/runNamelists.sh", + // "dependencies" : { "build-serial" : "afterok" } + // }, + "testcase-serial3" : + { + "submit_options" : { "timelimit" : "00:40:00" }, + "command" : ".ci/tests/runNamelists.sh", + "dependencies" : { "build-serial" : "afterok" } + }, + "build-omp" : + { + "command" : ".ci/tests/build.sh", + "dependencies" : + { + // We parallelized the serial tests, now sync + "testcase-serial0" : "afterok", + "testcase-serial1" : "afterok", + // "testcase-serial2" : "afterok", + "testcase-serial3" : "afterok" + } + }, + "testcase-omp0" : + { + "submit_options" : { "timelimit" : "00:25:00" }, + "command" : ".ci/tests/runNamelists.sh", + "dependencies" : { "build-omp" : "afterok" } + }, + "testcase-omp1" : + { + "submit_options" : { "timelimit" : "00:25:00" }, + "command" : ".ci/tests/runNamelists.sh", + "dependencies" : { "testcase-omp0" : "afterok" } + }, + // "testcase-omp2" : + // { + // "submit_options" : { "timelimit" : "00:25:00" }, + // "command" : ".ci/tests/runNamelists.sh", + // "dependencies" : { "testcase-omp1" : "afterok" } + // }, + "testcase-omp3" : + { + "submit_options" : { "timelimit" : "00:25:00" }, + "command" : ".ci/tests/runNamelists.sh", + "dependencies" : { "testcase-omp1" : "afterok" } + }, + "build-mpi" : + { + "command" : ".ci/tests/build.sh", + "dependencies" : { "testcase-omp3" : "afterok" } + }, + "testcase-mpi0" : + { + "submit_options" : { "timelimit" : "00:20:00" }, + "command" : ".ci/tests/runNamelists.sh", + "dependencies" : { "build-mpi" : "afterok" } + }, + "testcase-mpi1" : + { + "submit_options" : { "timelimit" : "00:20:00" }, + "command" : ".ci/tests/runNamelists.sh", + "dependencies" : { "testcase-mpi0" : "afterok" } + }, + // "testcase-mpi2" : + // { + // "submit_options" : { "timelimit" : "00:20:00" }, + // "command" : ".ci/tests/runNamelists.sh", + // "dependencies" : { "testcase-mpi1" : "afterok" } + // }, + "testcase-mpi3" : + { + "submit_options" : { "timelimit" : "00:20:00" }, + "command" : ".ci/tests/runNamelists.sh", + "dependencies" : { "testcase-mpi1" : "afterok" } + } + } + }, + "em_real8" : + { + "submit_options" : + { + "arguments" : + { + ".*build.*::args_configopt" : [ "-o", "-d -r8" ], + ".*testcase.*::args_namelist" : + [ + "-n", "namelist.input.14,namelist.input.17AD", + "-e", "NAMELIST_DIR=em_real8" + ] + } + }, + "steps" : + { + "build-serial" : + { + "command" : ".ci/tests/build.sh" + }, + "testcase-serial" : + { + "command" : ".ci/tests/runNamelists.sh", + "dependencies" : { "build-serial" : "afterok" } + }, + "build-omp" : + { + "command" : ".ci/tests/build.sh", + "dependencies" : { "testcase-serial" : "afterok" } + }, + "testcase-omp" : + { + "command" : ".ci/tests/runNamelists.sh", + "dependencies" : { "build-omp" : "afterok" } + }, + "build-mpi" : + { + "command" : ".ci/tests/build.sh", + "dependencies" : { "testcase-omp" : "afterok" } + }, + "testcase-mpi" : + { + "command" : ".ci/tests/runNamelists.sh", + "dependencies" : { "build-mpi" : "afterok" } + } + } + }, + "em_realA" : + { + "submit_options" : + { + "arguments" : + { + ".*testcase.*::args_namelist" : + [ + // The following namelists require BUILD_RRTMG_FAST and BUILD_RRTMK + // namelist.input.03 + "-n", "namelist.input.03DF", + "-e", "NAMELIST_DIR=em_realA" + ] + } + }, + "steps" : + { + "build-serial" : + { + "command" : ".ci/tests/build.sh" + }, + "testcase-serial" : + { + "command" : ".ci/tests/runNamelists.sh", + "dependencies" : { "build-serial" : "afterok" } + }, + "build-omp" : + { + "command" : ".ci/tests/build.sh", + "dependencies" : { "testcase-serial" : "afterok" } + }, + "testcase-omp" : + { + "command" : ".ci/tests/runNamelists.sh", + "dependencies" : { "build-omp" : "afterok" } + }, + "build-mpi" : + { + "command" : ".ci/tests/build.sh", + "dependencies" : { "testcase-omp" : "afterok" } + }, + "testcase-mpi" : + { + "command" : ".ci/tests/runNamelists.sh", + "dependencies" : { "build-mpi" : "afterok" } + } + } + }, + "em_realB" : + { + "submit_options" : + { + "arguments" : + { + ".*testcase.*::args_namelist" : + [ + "-n", "namelist.input.10,namelist.input.11,namelist.input.14", + "-e", "NAMELIST_DIR=em_realB" + ] + } + }, + "steps" : + { + "build-serial" : + { + "command" : ".ci/tests/build.sh" + }, + "testcase-serial" : + { + "command" : ".ci/tests/runNamelists.sh", + "dependencies" : { "build-serial" : "afterok" } + }, + "build-omp" : + { + "command" : ".ci/tests/build.sh", + "dependencies" : { "testcase-serial" : "afterok" } + }, + "testcase-omp" : + { + "command" : ".ci/tests/runNamelists.sh", + "dependencies" : { "build-omp" : "afterok" } + }, + "build-mpi" : + { + "command" : ".ci/tests/build.sh", + "dependencies" : { "testcase-omp" : "afterok" } + }, + "testcase-mpi" : + { + "command" : ".ci/tests/runNamelists.sh", + "dependencies" : { "build-mpi" : "afterok" } + } + } + }, + "em_realC" : + { + "submit_options" : + { + "arguments" : + { + ".*testcase.*::args_namelist" : + [ + "-n", "namelist.input.17,namelist.input.20", + "-e", "NAMELIST_DIR=em_realC" + ] + } + }, + "steps" : + { + "build-serial" : + { + "command" : ".ci/tests/build.sh" + }, + "testcase-serial" : + { + "command" : ".ci/tests/runNamelists.sh", + "dependencies" : { "build-serial" : "afterok" } + }, + "build-omp" : + { + "command" : ".ci/tests/build.sh", + "dependencies" : { "testcase-serial" : "afterok" } + }, + "testcase-omp" : + { + "command" : ".ci/tests/runNamelists.sh", + "dependencies" : { "build-omp" : "afterok" } + }, + "build-mpi" : + { + "command" : ".ci/tests/build.sh", + "dependencies" : { "testcase-omp" : "afterok" } + }, + "testcase-mpi" : + { + "command" : ".ci/tests/runNamelists.sh", + "dependencies" : { "build-mpi" : "afterok" } + } + } + }, + "em_realD" : + { + "submit_options" : + { + "arguments" : + { + ".*testcase.*::args_namelist" : + [ + "-n", "namelist.input.38", + // The following namelists require BUILD_RRTMG_FAST and BUILD_RRTMK + // ,namelist.input.48,namelist.input.49", + "-e", "NAMELIST_DIR=em_realD" + ] + } + }, + "steps" : + { + "build-serial" : + { + "command" : ".ci/tests/build.sh" + }, + "testcase-serial" : + { + "command" : ".ci/tests/runNamelists.sh", + "dependencies" : { "build-serial" : "afterok" } + }, + "build-omp" : + { + "command" : ".ci/tests/build.sh", + "dependencies" : { "testcase-serial" : "afterok" } + }, + "testcase-omp" : + { + "command" : ".ci/tests/runNamelists.sh", + "dependencies" : { "build-omp" : "afterok" } + }, + "build-mpi" : + { + "command" : ".ci/tests/build.sh", + "dependencies" : { "testcase-omp" : "afterok" } + }, + "testcase-mpi" : + { + "command" : ".ci/tests/runNamelists.sh", + "dependencies" : { "build-mpi" : "afterok" } + } + } + }, + // "em_realE" : + // { + // "submit_options" : + // { + // "arguments" : + // { + // ".*testcase.*::args_namelist" : + // [ + // "-n", "namelist.input.52DF", + // "-e", "NAMELIST_DIR=em_realE" + // ] + // } + // }, + // "steps" : + // { + // "build-serial" : + // { + // "command" : ".ci/tests/build.sh" + // }, + // "testcase-serial" : + // { + // "command" : ".ci/tests/runNamelists.sh", + // "dependencies" : { "build-serial" : "afterok" } + // }, + // "build-omp" : + // { + // "command" : ".ci/tests/build.sh", + // "dependencies" : { "testcase-serial" : "afterok" } + // }, + // "testcase-omp" : + // { + // "command" : ".ci/tests/runNamelists.sh", + // "dependencies" : { "build-omp" : "afterok" } + // }, + // "build-mpi" : + // { + // "command" : ".ci/tests/build.sh", + // "dependencies" : { "testcase-omp" : "afterok" } + // }, + // "testcase-mpi" : + // { + // "command" : ".ci/tests/runNamelists.sh", + // "dependencies" : { "build-mpi" : "afterok" } + // } + // } + // }, + "em_realF" : + { + "submit_options" : + { + "timelimit" : "00:40:00", + "arguments" : + { + ".*testcase.*::args_namelist" : + [ + "-n", "namelist.input.65DF", + "-e", "NAMELIST_DIR=em_realF" + ] + } + }, + "steps" : + { + "build-serial" : + { + "command" : ".ci/tests/build.sh" + }, + "testcase-serial" : + { + "command" : ".ci/tests/runNamelists.sh", + "dependencies" : { "build-serial" : "afterok" } + }, + "build-omp" : + { + "command" : ".ci/tests/build.sh", + "dependencies" : { "testcase-serial" : "afterok" } + }, + "testcase-omp" : + { + "command" : ".ci/tests/runNamelists.sh", + "dependencies" : { "build-omp" : "afterok" } + }, + "build-mpi" : + { + "command" : ".ci/tests/build.sh", + "dependencies" : { "testcase-omp" : "afterok" } + }, + "testcase-mpi" : + { + "command" : ".ci/tests/runNamelists.sh", + "dependencies" : { "build-mpi" : "afterok" } + } + } + }, + // This requires BUILD_RRTMG_FAST and BUILD_RRTMK + // "em_realG" : + // { + // "submit_options" : + // { + // "arguments" : + // { + // ".*testcase.*::args_namelist" : + // [ + // "-n", "namelist.input.kiaps1NE,namelist.input.kiaps2", + // "-e", "NAMELIST_DIR=em_realG" + // ] + // } + // }, + // "steps" : + // { + // "build-serial" : + // { + // "command" : ".ci/tests/build.sh" + // }, + // "testcase-serial" : + // { + // "command" : ".ci/tests/runNamelists.sh", + // "dependencies" : { "build-serial" : "afterok" } + // }, + // "build-omp" : + // { + // "command" : ".ci/tests/build.sh", + // "dependencies" : { "testcase-serial" : "afterok" } + // }, + // "testcase-omp" : + // { + // "command" : ".ci/tests/runNamelists.sh", + // "dependencies" : { "build-omp" : "afterok" } + // }, + // "build-mpi" : + // { + // "command" : ".ci/tests/build.sh", + // "dependencies" : { "testcase-omp" : "afterok" } + // }, + // "testcase-mpi" : + // { + // "command" : ".ci/tests/runNamelists.sh", + // "dependencies" : { "build-mpi" : "afterok" } + // } + // } + // }, + "em_realH" : + { + "submit_options" : + { + "arguments" : + { + ".*testcase.*::args_namelist" : + [ + "-n", "namelist.input.52,namelist.input.cmt,namelist.input.solaraNE,namelist.input.urb3bNE,namelist.input.03ST", + "-e", "NAMELIST_DIR=em_realH" + ] + } + }, + "steps" : + { + "build-serial" : + { + "command" : ".ci/tests/build.sh" + }, + "testcase-serial" : + { + "command" : ".ci/tests/runNamelists.sh", + "dependencies" : { "build-serial" : "afterok" } + }, + "build-mpi" : + { + "command" : ".ci/tests/build.sh", + "dependencies" : { "testcase-serial" : "afterok" } + }, + "testcase-mpi" : + { + "command" : ".ci/tests/runNamelists.sh", + "dependencies" : { "build-mpi" : "afterok" } + } + } + }, + "em_realI" : + { + "submit_options" : + { + "arguments" : + { + ".*testcase.*::args_namelist" : + [ + "-n", "namelist.input.03FD,namelist.input.06", + "-e", "NAMELIST_DIR=em_realI" + ] + } + }, + "steps" : + { + "build-serial" : + { + "command" : ".ci/tests/build.sh" + }, + "testcase-serial" : + { + "command" : ".ci/tests/runNamelists.sh", + "dependencies" : { "build-serial" : "afterok" } + }, + "build-omp" : + { + "command" : ".ci/tests/build.sh", + "dependencies" : { "testcase-serial" : "afterok" } + }, + "testcase-omp" : + { + "command" : ".ci/tests/runNamelists.sh", + "dependencies" : { "build-omp" : "afterok" } + }, + "build-mpi" : + { + "command" : ".ci/tests/build.sh", + "dependencies" : { "testcase-omp" : "afterok" } + }, + "testcase-mpi" : + { + "command" : ".ci/tests/runNamelists.sh", + "dependencies" : { "build-mpi" : "afterok" } + } + } + }, + "em_realJ" : + { + "submit_options" : + { + "arguments" : + { + ".*testcase.*::args_namelist" : + [ + "-n", "namelist.input.50,namelist.input.51", + "-e", "NAMELIST_DIR=em_realJ" + ] + } + }, + "steps" : + { + "build-serial" : + { + "command" : ".ci/tests/build.sh" + }, + "testcase-serial" : + { + "command" : ".ci/tests/runNamelists.sh", + "dependencies" : { "build-serial" : "afterok" } + }, + "build-omp" : + { + "command" : ".ci/tests/build.sh", + "dependencies" : { "testcase-serial" : "afterok" } + }, + "testcase-omp" : + { + "command" : ".ci/tests/runNamelists.sh", + "dependencies" : { "build-omp" : "afterok" } + }, + "build-mpi" : + { + "command" : ".ci/tests/build.sh", + "dependencies" : { "testcase-omp" : "afterok" } + }, + "testcase-mpi" : + { + "command" : ".ci/tests/runNamelists.sh", + "dependencies" : { "build-mpi" : "afterok" } + } + } + }, + "em_realK" : + { + "submit_options" : + { + "arguments" : + { + ".*testcase.*::args_namelist" : + [ + "-n", "namelist.input.52FD,namelist.input.60NE", + "-e", "NAMELIST_DIR=em_realK" + ] + } + }, + "steps" : + { + "build-serial" : + { + "command" : ".ci/tests/build.sh" + }, + "testcase-serial" : + { + "command" : ".ci/tests/runNamelists.sh", + "dependencies" : { "build-serial" : "afterok" } + }, + "build-omp" : + { + "command" : ".ci/tests/build.sh", + "dependencies" : { "testcase-serial" : "afterok" } + }, + "testcase-omp" : + { + "command" : ".ci/tests/runNamelists.sh", + "dependencies" : { "build-omp" : "afterok" } + }, + "build-mpi" : + { + "command" : ".ci/tests/build.sh", + "dependencies" : { "testcase-omp" : "afterok" } + }, + "testcase-mpi" : + { + "command" : ".ci/tests/runNamelists.sh", + "dependencies" : { "build-mpi" : "afterok" } + } + } + }, + "em_realL" : + { + "submit_options" : + { + "arguments" : + { + ".*testcase.*::args_namelist_dir" : [ ], + ".*testcase.*0.*::args_namelist" : + [ + "-n", "namelist.input.66FD", + "-e", "NAMELIST_DIR=em_realL", + "-r", "runNamelists/$NAMELIST_DIR/0" + ], + ".*testcase.*1.*::args_namelist" : + [ + "-n", "namelist.input.71", + "-e", "NAMELIST_DIR=em_realL", + "-r", "runNamelists/$NAMELIST_DIR/1" + ], + ".*testcase.*2.*::args_namelist" : + [ + "-n", "namelist.input.78,namelist.input.79", + "-e", "NAMELIST_DIR=em_realL", + "-r", "runNamelists/$NAMELIST_DIR/1" + ] + } + }, + "steps" : + { + "build-serial" : + { + "command" : ".ci/tests/build.sh" + }, + "testcase-serial0" : + { + "submit_options" : { "timelimit" : "00:30:00" }, + "command" : ".ci/tests/runNamelists.sh", + "dependencies" : { "build-serial" : "afterok" } + }, + "testcase-serial1" : + { + "submit_options" : { "timelimit" : "00:30:00" }, + "command" : ".ci/tests/runNamelists.sh", + "dependencies" : { "build-serial" : "afterok" } + }, + "testcase-serial2" : + { + "submit_options" : { "timelimit" : "00:30:00" }, + "command" : ".ci/tests/runNamelists.sh", + "dependencies" : { "build-serial" : "afterok" } + }, + "build-omp" : + { + "command" : ".ci/tests/build.sh", + "dependencies" : { "testcase-serial0" : "afterok", "testcase-serial1" : "afterok", "testcase-serial2" : "afterok" } + }, + "testcase-omp0" : + { + "command" : ".ci/tests/runNamelists.sh", + "dependencies" : { "build-omp" : "afterok" } + }, + "testcase-omp1" : + { + "command" : ".ci/tests/runNamelists.sh", + "dependencies" : { "testcase-omp0" : "afterok" } + }, + "testcase-omp2" : + { + "command" : ".ci/tests/runNamelists.sh", + "dependencies" : { "testcase-omp1" : "afterok" } + }, + "build-mpi" : + { + "command" : ".ci/tests/build.sh", + "dependencies" : { "testcase-omp2" : "afterok" } + }, + "testcase-mpi0" : + { + "command" : ".ci/tests/runNamelists.sh", + "dependencies" : { "build-mpi" : "afterok" } + }, + "testcase-mpi1" : + { + "command" : ".ci/tests/runNamelists.sh", + "dependencies" : { "testcase-mpi0" : "afterok" } + }, + "testcase-mpi2" : + { + "command" : ".ci/tests/runNamelists.sh", + "dependencies" : { "testcase-mpi1" : "afterok" } + } + } + } +} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 79a88db082..81d66e4e71 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,6 +32,7 @@ on: options: - all-tests - compile-tests + - em_real-tests # https://docs.github.com/en/actions/sharing-automations/reusing-workflows#supported-keywords-for-jobs-that-call-a-reusable-workflow @@ -66,8 +67,8 @@ jobs: account : NMMM0012 name : "Make Compilation Tests" id : make-tests - fileroot : wrf_compilation_tests-make - args : -j='{"node_select":{"-l ":{"select":1}}}' + config : .ci/wrf_compilation_tests-make.json + args : -ff hsn.de.hpc.ucar.edu -j='{"node_select":{"-l ":{"select":1}}}' pool : 8 tpool : 1 mkdirs : true @@ -102,7 +103,79 @@ jobs: name : ${{ matrix.testSet.name }} id : ${{ matrix.testSet.id }} host : ${{ matrix.testSet.host }} - fileroot : ${{ matrix.testSet.fileroot }} + config : ${{ matrix.testSet.config }} + account : ${{ matrix.testSet.account }} + tests : ${{ toJson( matrix.testSet.tests ) }} + mkdirs : ${{ matrix.testSet.mkdirs }} + args : ${{ matrix.testSet.args }} + pool : ${{ matrix.testSet.pool }} + tpool : ${{ matrix.testSet.tpool }} + + # required to emulate event trigger + event_name : ${{ inputs.event_name }} + event_number : ${{ inputs.event_number }} + event_label : ${{ inputs.test }} + ref : ${{ inputs.ref }} + sha : ${{ inputs.sha }} + + # I am leaving this here for posterity if this is to be replicated in private repositories for testing + permissions: + contents: read + pull-requests: write + statuses: write + name : Test ${{ matrix.testSet.name }} on ${{ matrix.testSet.host }} + + em_real: + if : ${{ contains( fromJson('["em_real-tests","all-tests"]'), inputs.test ) || inputs.event_name == 'push' }} + strategy: + max-parallel: 4 + fail-fast: false + matrix: + + testSet : + - host : derecho + hpc-workflows_path : .ci/hpc-workflows + archive : /glade/work/aislas/github/runners/wrf/derecho/logs/ + account : NMMM0012 + name : "em_real Tests" + id : em_real-tests + config : .ci/wrf_em_real_tests.jsonc + args : -ff hsn.de.hpc.ucar.edu -j='{"node_select":{"-l ":{"select":1}}}' + pool : 14 + tpool : 4 # This really only applies to em_real and em_realL + mkdirs : true + tests : + - em_real + - em_real8 + - em_realA # partially implemented + - em_realB + - em_realC + - em_realD # partially implemented + # This test intermittently fails + # - em_realE + - em_realF + # This test requires BUILD_RRTMG_FAST and BUILD_RRTMK + # - em_realG + # Unstable and cannot get bitwise identical results + # - em_realH + # - em_realI + # - em_realJ + # - em_realK + # - em_realL + + uses : ./.github/workflows/test_workflow.yml + with : + # This should be the only hard-coded value, we don't use ${{ inputs.test }} + # to avoid 'all-tests' to be used in this workflow + label : em_real-tests + + # Everything below this should remain the same and comes from the testSet matrix + hpc-workflows_path : ${{ matrix.testSet.hpc-workflows_path }} + archive : ${{ matrix.testSet.archive }} + name : ${{ matrix.testSet.name }} + id : ${{ matrix.testSet.id }} + host : ${{ matrix.testSet.host }} + config : ${{ matrix.testSet.config }} account : ${{ matrix.testSet.account }} tests : ${{ toJson( matrix.testSet.tests ) }} mkdirs : ${{ matrix.testSet.mkdirs }} diff --git a/.github/workflows/entry_point.yml b/.github/workflows/entry_point.yml index ed4ce200cd..04cad8fcdc 100644 --- a/.github/workflows/entry_point.yml +++ b/.github/workflows/entry_point.yml @@ -22,7 +22,12 @@ on: # https://stackoverflow.com/a/68940067 jobs: queue_tests: - if : ${{ contains( fromJson('["compile-tests","all-tests"]'), github.event.label.name ) || github.event_name == 'push' }} + # https://stackoverflow.com/a/67532120 + if : > + ${{ contains( + fromJson('["compile-tests","em_real-tests","all-tests"]'), + github.event.label.name ) || + github.event_name == 'push' }} name: Queue Test (${{ github.event_name == 'push' && github.ref_name || github.event.label.name }}) runs-on: ubuntu-latest permissions: diff --git a/.github/workflows/test_workflow.yml b/.github/workflows/test_workflow.yml index a4060dcb6c..8468956a9a 100644 --- a/.github/workflows/test_workflow.yml +++ b/.github/workflows/test_workflow.yml @@ -22,7 +22,7 @@ on : host : required : true type : string - fileroot : + config : required : true type : string account : @@ -94,12 +94,31 @@ jobs: state: 'pending' }) + - name: Get fileroot of test config + id: get_fileroot + run: | + filename=$( basename ${{ inputs.config }} ) + echo "rel_dir=$( dirname ${{ inputs.config }} )" >> "$GITHUB_ENV" + echo "fileroot=${filename%.*}" >> "$GITHUB_ENV" + - uses: actions/checkout@v4 with: path : main submodules: true ref: ${{ inputs.event_name == 'push' && github.ref || inputs.ref }} + ############################################################################ + # WRF Specific + # More checkout, just do everything so we have it all at the ready. This unfortunately will limit testing + # of on-the-fly checkouts + - name: Checkout extra via manage_externals + id : manage_externals + run : | + cd main + ./tools/manage_externals/checkout_externals -e arch/Externals.cfg + ./tools/manage_externals/checkout_externals -e arch/OptionalExternals_testing.cfg + ############################################################################ + # Immediately copy out to # of tests to do - name: Create testing directories @@ -120,10 +139,10 @@ jobs: id : runTest run: | if [ "${{ inputs.mkdirs }}" = "true" ]; then - ALT_DIRS="-alt ../${{ join( fromJson( inputs.tests ), '/.ci ../' ) }}/.ci" + ALT_DIRS="-alt ../${{ join( fromJson( inputs.tests ), format( '/{0} ../', env.rel_dir ) ) }}/$rel_dir" fi ./main/${{ inputs.hpc-workflows_path }}/.ci/runner.py \ - ./main/.ci/${{ inputs.fileroot }}.json \ + ./main/${{ inputs.config }} \ -t ${{ join( fromJson( inputs.tests ), ' ' ) }} \ -a "${{ inputs.account }}" \ -p ${{ inputs.pool}} -tp ${{ inputs.tpool }} \ @@ -135,14 +154,14 @@ jobs: if : ${{ failure() }} run : | # move log files to safe location - ./main/${{ inputs.hpc-workflows_path }}/.ci/relocator.py ./main/.ci/${{ inputs.fileroot }}.log ${{ inputs.archive }}/$LOG_SUFFIX/${{ inputs.id }} + ./main/${{ inputs.hpc-workflows_path }}/.ci/relocator.py ./main/$rel_dir/$fileroot.log ${{ inputs.archive }}/$LOG_SUFFIX/${{ inputs.id }} # report on them - alt dirs need extra help if [ "${{ inputs.mkdirs }}" = "true" ]; then - masterlogLoc=main/.ci + masterlogLoc=main/$rel_dir fi - ./main/${{ inputs.hpc-workflows_path }}/.ci/reporter.py ${{ inputs.archive }}/$LOG_SUFFIX/${{ inputs.id }}/$masterlogLoc/${{ inputs.fileroot }}.log \ - -e ./${{ inputs.hpc-workflows_path }}/.ci/runner.py -p ./.ci \ + ./main/${{ inputs.hpc-workflows_path }}/.ci/reporter.py ${{ inputs.archive }}/$LOG_SUFFIX/${{ inputs.id }}/$masterlogLoc/$fileroot.log \ + -e ./${{ inputs.hpc-workflows_path }}/.ci/runner.py -p ./$rel_dir \ -o GITHUB -m -n # only mark fail steps with gh syntax echo "Relaying results to summary..." @@ -150,8 +169,8 @@ jobs: # report on them echo "# Summary for ${{ inputs.name }}" >> $GITHUB_STEP_SUMMARY echo "\`\`\`" >> $GITHUB_STEP_SUMMARY - ./main/${{ inputs.hpc-workflows_path }}/.ci/reporter.py ${{ inputs.archive }}/$LOG_SUFFIX/${{ inputs.id }}/$masterlogLoc/${{ inputs.fileroot }}.log \ - -e ./${{ inputs.hpc-workflows_path }}/.ci/runner.py -p ./.ci \ + ./main/${{ inputs.hpc-workflows_path }}/.ci/reporter.py ${{ inputs.archive }}/$LOG_SUFFIX/${{ inputs.id }}/$masterlogLoc/$fileroot.log \ + -e ./${{ inputs.hpc-workflows_path }}/.ci/runner.py -p ./$rel_dir \ -s -n >> $GITHUB_STEP_SUMMARY echo "\`\`\`" >> $GITHUB_STEP_SUMMARY # We know this is a failure diff --git a/arch/OptionalExternals_testing.cfg b/arch/OptionalExternals_testing.cfg new file mode 100644 index 0000000000..b25e87d510 --- /dev/null +++ b/arch/OptionalExternals_testing.cfg @@ -0,0 +1,10 @@ +[testing_namelists] +local_path = .ci/tests/SCRIPTS +protocol = git +repo_url = https://github.com/wrf-model/SCRIPTS.git +hash = 416918d + +required = True + +[externals_description] +schema_version = 1.0.0