Writing an Assignment Configuration
This is a quick-start guide to writing your own Assignment Configuration YAML. Note that this document is by no means comprehensive; The Grader is much more extensible than what is advertised here.
Template
A starting template can be found here
. The file will contain a one-liner
description of which required option does. Alternatively, an unannotated version can be found
here
.
The following sections will all use the above template to briefly explain the meaning of each configuration option. Always refer to configuration-specific documents for more details on how to use each stage!
Settings
The _settings
block is used to configure global grading options.
_settings:
lang: cpp/g++:8
use_template: FILENAMES
template:
- do_not_include.txt
use_skeleton: true
use_provided: true
stage_wait_duration_secs: 10
cpus: 1.0
mem_gb: 2.0
enable_features:
network: false
gpu_device: ~
The most important configuration keys are explained below.
lang
This key determines the programming language which this grading pipeline is targeted for.
Certain stages, such as Compile and StdioTest, contain custom language-specific logic. By setting this key, it allows those stages to adapt its execution for the specified language.
The currently supported languages are:
cpp/g++:<gcc_version>
Supports any GCC version 8 or above
<gcc_version>
can be the full version (9.3.0
), major+minor version (9.3
), or major version only (9
)
java:<java_version>
Supports any Java version 7 or above
For Java versions 8 or below,
<java_version>
can be the full version (8u282
) or major version only (8
)For Java versions 9 or above,
<java_version>
can be the full version (11.0.10
), major+minor version (11.0
), or major version only (11
)
python:<python_version>
Supports Python 2 and 3
<python_version>
can be the full version (3.8.7
), major+minor version (3.8
), or major version only (3
)
We also support additional frameworks like Qt for C++. For such cases, you will need to specify the framework instead of the programming language in this field.
cuda/python:<cuda_version>
Uses Python bundled with the distribution, therefore its version cannot be specified
Refer to table in Assignment Configuration for the supported versions matrix and the corresponding Python versions
<cuda_version>
must be the full version of CUDA (11.5.1
), optionally postfixed by-cudnn
if cuDNN libraries are needed (11.5.1-cudnn
)
qt5:<debian_version>
The Qt version is based on the version shipped by the Debian Linux distribution.
- We officially support the
<debian_version>
below, other versions are not tested: buster
, with Qt55.11.3
and g++8.3.0
- We officially support the
use_template
and template
This key specifies whether template files or filenames are available for stages to use.
Template files (or filenames) are the list of files which students are expected to submit for an assignment. This list
can be provided either as part of the Helper Files package, or listed in this configuration as part of template
.
This field should be set to PATH
if the template files are provided as part of the Helper Files package; This
field should be set to FILENAMES
if the template filenames are provided by this configuration, and
_settings.template
should be populated appropriately. To indicate that template files will not be used, this key
should be removed.
_settings.template
does not need to be present in the _settings
object if use_template
is not set to
FILENAMES
.
use_skeleton
This key specifies whether skeleton files are available for stages to use.
Skeleton files are the files provided to students which act as starting code for the assignment. This list can be provided as part of the Helper Files package.
This field should be set to true
if the skeleton files are provided. Otherwise, the field can be set to false
,
or the field can be removed from the _settings
object.
use_provided
This key specifies whether provided files are available for stages to use.
Provided files are the files used only in the grading process. These files are typically for internal use and are not provided to students. Examples for provided files are driver code for grading student submissions, and test case code which are hidden from students.
This list can be provided as part of the Helper Files package.
This field should be set to true
if the provided files are provided. Otherwise, the field can be set to false
,
or the field can be removed from the _settings
object.
stage_wait_duration_secs
This key specifies the timeout for each stage in seconds.
The most common purpose of this key is to limit how long stages can run, to allow the grading process to continue if specific test cases take too long (e.g. due to an infinite loop or broken I/O).
Tuning this number can be very difficult, as the optimal value depends on the longest running stage of your grading pipeline and the performance of the server. In general, you should time how long the grading process takes on your local machine, and multiply that by 2-3 times for a good estimate of this value.
Note
Do not set this value too low or too high. Setting this value too low will cause grading stages to be killed before it can start executing; Setting this value too high can cause other grading tasks (including those from other courses) to be choked out, creating a huge backlog of grading tasks!
A good minimum value is 10 seconds, whereas a good maximum value is 120 seconds. Only go above if your stage(s) require it!
cpus
This key specifies how many cores each stage can use.
In general, setting this key to 1.0
implies that a single core is available to each stage. More specifically, this
value actually sets the amount of CPU-time stages are allocated, and 1.0
implies that one CPU worth of time is
available to each stage. If the stage exhausts the allocated CPU-time, the task will be evicted by the OS scheduler
until more CPU-time is available.
Note that the setting of this value may have an impact to _settings.stage_wait_duration_secs
, as certain stages may
be able to use multiple threads to accelerate its workload.
In general, this key should be set to 1.0
, unless your grading pipeline contains stages which can exploit
parallelism, such as Make (using jobserver mode).
Note
Do not set this value too high, as it may impact the throughput of the Grader with regards with grading other submissions. In fact, setting this value too high may cause your grading task to be rejected, as no online servers can fulfill the amount of CPUs requested.
Please be courteous to other users and only set this value up to what is necessary.
mem_gb
This key specifies how much RAM each stage can use.
In general, setting this key to 1.0
implies that 1 GB of RAM is available to each stage. If the stage exhausts the
allocated RAM, the stage will be terminated with a SIGKILL
(or equivalent) signal.
In general, this key should be set to 1.0
, unless your grading pipeline contains stages which require more RAM, such
as when using build systems for compilation.
Note
Do not set this value too high, as it may impact the throughput of the Grader with regards with grading other submissions. In fact, setting this value too high may cause your grading task to be rejected, as no online servers can fulfill the amount of RAM requested.
Please be courteous to other users and only set this value up to what is necessary.
early_return_on_throw
This key specifies whether to terminate the entire grading task if any non-failable stage has failed.
When certain pipeline stages fail, such as compilation stages, it often makes no sense to continue grading, as the
artifacts required by subsequent stages are not generated. Setting this option to true
will cause these stages to be
marked as “unfailable”, meaning that if the grading task will be aborted if the stage fails.
Warning
This option is experimental, as the Grader has only been tested with this option turned off.
Use at your own risk!
enabled_features
This key specifies a list of features which should be enabled/disabled for this assignment configuration. The key accepts the following key-value pairs:
network
(Default:true
)If enabled, all stages in the pipeline has access to the Internet.
gpu_device
(Default:null
)If specified, the Grader will allocate a GPU from one of the specified vendor(s) and attach it to all pipeline stages.
The list of recognized vendors are:
NVIDIA
: Use any NVIDIA GPUsAMD
: Use any AMD GPUsINTEL
: Use any Intel GPUs
For example, to enable the use of NVIDIA GPUs (because, e.g., your pipeline stage requires the use of CUDA), set this key as:
gpu_device: - NVIDIA
To enable the use of either an AMD or Intel GPU (because, e.g., your pipeline stage requires using the Mesa open-source drivers), set this key as:
gpu_device: - AMD - INTEL
Additionally, this key also accepts a string
ANY
, which indicates that the pipeline requires the presence of any GPUs. Note that this option also considers GPUs exposed as virtual machine devices, e.g. VMWare VGA controller, as a viable candidate.To enable the use of any GPU, set this key as:
gpu_device: ANY
Note
The Grader can only guarantee that a GPU of any of the listed vendors is allocated. Specific models of GPUs cannot be requested to be allocated, as the hardware backing the Grader may change without prior notice (including upgrades), which may silently break pipelines if a specific GPU is pinned.
Pipeline Stages Overview
To adapt to the different grading requirements for different courses, the grading process is represented as a list of execution stages, forming a grading pipeline. Each student submission will be executed using the grading pipeline.
Grader pipeline stages are generally categorized into three types: Pre-Grading Stages, Grading Stages, and Post-Grading Stages.
Configuration Format
When configuring a pipeline stage, the configuration will generally look like this:
<stageName>:
key1: value1
key2: value2
key3: value3
Each <stageName>
will represent one instance of the stage within the pipeline. The stage configurations should be
declared in the order you want the stages to execute in.
For example, the following YAML will build a pipeline which runs the stages in the following order:
fileStructureValidation
diffWithSkeleton
compile
stdioTest
score
fileStructureValidation: {}
diffWithSkeleton: {}
compile:
# ...
stdioTest:
# ...
score:
# ...
Note
The Grader may perform some rudimentary reordering to ensure that no illogical pipelines are created. For example,
pipelines which execute stdioTest
before compile
may be reordered to ensure that compilation is always
performed before testing.
Multiple Stages of Same Type
Multiple stages with the same type are also supported in the configuration format; Append :
with a custom name to
allow Grader to differentiate between the different stages.
For example, in a C++ separate compilation pipeline, the following shows an example of compiling two files into their respective object files, before linking together.
compile:main:
input: ["main.cpp"]
output: "main.o"
flags:
- '-c'
compile:student:
input: ["student.cpp"]
output: "student.o"
flags:
- '-c'
compile:link:
input:
- main.o
- student.o
output: a.out
Note that for consecutive stages of the same type, the Grader will execute each stage in the order it is declared. For
the above configuration, this means that compile:main
will first run, followed by compile:student
, and finally
compile:link
.
Pre-Grading Stages
Pre-Grading Stages are pipeline stages which are performed before compilation and/or test execution. These stages are generally language-agnostic in nature.
fileStructureValidation
File Structure Validation is a stage which checks whether files submitted by the students matches the expected list of files that students should submit. If the student submission does not contain certain files, or the student submission contains additional files, this stage will emit a warning for students.
Note that in order to use this stage, _settings.use_template
must not be null
.
diffWithSkeleton
Diff With Skeleton is a stage which checks whether students have inadvertently submitted certain files from the skeleton code. If there are any files in the student submission which are identical to those in the skeleton code, this stage will emit a warning for students.
Note that in order to use this stage, _settings.use_skeleton
must be true
.
Grading Stages
Grading Stages are pipeline stages which are performed to either prepare or execute grading tasks. Some of these stages have the additional ability to be score-generating, i.e. a score can be generated from the stage based on its correctness.
Since different programming languages have different tools for compilation and testing, this section will be split based on the programming language.
Note that the following sections are not an exhaustive list of all supported stages. Refer to this page for a comprehensive list of supported stages and their configuration.
Language-Agnostic
Compile
The Compile stage is a language-agnostic stage which can be used in any pipeline with a supported _settings.lang
.
This allows you to only need to specify the input
, output
, and optionally the compilation flags to compile
file(s) using the compiler.
StdioTest
The Stdio Test stage is a language-agnostic stage which is used to perform testing using Standard I/O (i.e. stdout
and stderr
) streams.
C++
Make
Ths Make stage is a stage which invokes GNU Make on Makefile
for easier compilation.
Valgrind
The Valgrind stage is a stage which invokes Valgrind on an executable.
Note that the specification for Valgrind does not contain individual test cases. Instead, the Valgrind configuration is
designed to be applied to all test cases within all stdioTest
blocks. Fine-grained overrides can be configured using
the stdioTest.testCases.valgrind
key.
GTest
The GTest stage is a stage which compiles files containing GTest test cases and executes them.
Java
JUnit
The JUnit stage is a stage which compiles files containing JUnit test cases and executes them.
Note that this stage uses the JUnit Platform Runner provided by JUnit 5. While JUnit 5 test cases are natively supported, only part of JUnit 3 and JUnit 4’s feature set is supported.
Gradle
The Gradle stage is a stage which executes Gradle task(s) in a Gradle project.
Python
PyTest
The PyTest stage is a stage which executes PyTest test cases.
Note
To specify the Python modules required by this stage, use the additional_pip_packages
key in the stage
configuration.
Post-Grading Stages
Score
The Score stage performs aggregation on all score-generating stages preceding it.
Note
If this stage is not specified, an overall score will not be generated for submissions.