Faculty Users
This page has numerous guides for faculty users. See the nagivation bar to explore the sections on this page.
Client Setup
This guide details how to set up a faculty machine to use the git-keeper client. The client has been used successfully in OS X and Linux. It may work in Windows using the Windows Subsystem for Linux or Cygwin but that has not been fully tested.
Requirements
The client requires Git and Python 3.8 or greater.
In addition, you need the username and password sent to you by the
git-keeper server. This account must be created by the git-keeper
server. For the faculty admin, your account is created the first time
you run gkeepd. For other faculty, the faculty admin must use
gkeep add_faculty to create the account.
Installing the Client
To install the client system-wide, run the following command:
sudo python3 -m pip install git-keeper-client
Alternatively, you may want to install the client in a Python virtual environment if you do not want to clutter your system's Python packages.
Configuration
There must be a configuration file at ~/.config/git-keeper/client.cfg (or
$XDG_CONFIG_HOME/git-keeper/client.cfg if $XDG_CONFIG_HOME is set). The
easiest way to create this file is to run gkeep config, which will prompt you
for various values and then create the file.
If you create client.cfg manually, you must include a section called
[server] which defines the hostname of the server, your faculty username on
the server, and optionally the SSH server's port number which defaults to 22.
You may also include an optional section [local] in which you can define a
directory into which gkeep will fetch submissions and the directory where
assignment templates are stored. If present, these must be an absolute path.
Here is an example client.cfg:
[server]
host = gitkeeper.myhostname.com
username = myfacultyusername
# optional
ssh_port = 22
# optional section
[local]
submissions_path = ~/submissions
template_path = ~/gkeep_templates
SSH Key
The client communicates with the server over SSH, and it requires SSH keys so that you can make SSH connections without a password.
If you have never generated a public key, do so now:
ssh-keygen
Use the default filename, and do NOT set a password for the key.
Next, copy your public key to your git-keeper server:
ssh-copy-id <username>@<hostname>
Check Your Configuration
To verify that everything is configured correctly, run
gkeep check
The output should something look like:
/home/turing/.config/git-keeper/client.cfg parsed without errors
Successfully communicated with gkserver
Server information:
Version: 0.3.1
gkeepd uptime: 29m21s
Firejail installed: True
Docker installed: True
Getting Help
Run gkeep with no arguments to see a usage message. Run gkeep with a
subcommand and no additional arguments to see a usage message for that
subcommand.
Creating Classes
To create a class you first need to create a CSV file with the names and email
addresses of the students in the class. Class names are unique for each
faculty member and cannot be changed. We recommend you use a naming scheme
that includes information that identifies the course and the term. For
example, cs100f22.
To create a class named cs100f22, create a file named cs100f22.csv
containing something like the following:
Hamilton,Margaret,mhamilton@example.edu
Hopper,Grace,ghopper@example.edu
Lovelace,Ada,alovelace@example.edu
Now you can add the class on the server using gkeep:
gkeep add cs100f22 cs100f22.csv
An account will be created for any student in the class that does not already have an account on the server. The account name will be the username portion of the student's email address, though modifications will be performed if the email username is not a valid Linux username. In the case of a duplicate username, a number will be appended to the username to create a unique account. Passwords are randomly generated. An email containing the student's username and password will be sent to the student.
Note
Faculty should save the CSV file in case they need to make changes to
the enrollment of the class on the git-keeper server.
Modifying Classes
Faculty can use the gkeep modify command to:
- Add new students to a class
- Remove students from a class
- Change a student's name (e.g. fix a typo)
- Change a student's email address
The system uses the email address to identify the student, so it will consider a change of email address as removing the old account and adding a new account.
Faculty can make multiple changes to the CSV file and then run gkeep modify
to make all the changes at once. The system will show you the changes and
prompt you for confirmation.
Examples
In the following examples, assume you have a class named cs100f22 based on the
file cs100f22.csv:
Hamilton,Margaret,mhamilton@example.edu
Hopper,Grace,ghopper@example.edu
Lovelace,Ada,alovelace@example.edu
Example: Add a New Student to a Class
Edit the class CSV file to add the student information:
Hamilton,Margaret,mhamilton@example.edu
Hopper,Grace,ghopper@example.edu
Lovelace,Ada,alovelace@example.edu
Turing,Alan,turninga@example.edu
Modify the class enrollment and confirm the changes
gkeep modify cs100f22 cs100f22.csv
The output will be:
Modifying class cs100f22
The following students will be added to the class:
Turing, Alan, turninga@example.edu
Proceed? (Y/n) y
Students added successfully
Example: Remove a Student from a Class
Edit the class CSV file to remove the student information (removing Grace Hopper in this example):
Hamilton,Margaret,mhamilton@example.edu
Lovelace,Ada,alovelace@example.edu
Modify the class enrollment and confirm the changes
gkeep modify cs100f22 cs100f22.csv
The output will be:
Modifying class cs100f22
The following students will be removed from the class:
Hopper, Grace, ghopper@example.edu
Proceed? (Y/n) y
Students removed successfully
Example: Change the Name of a Student
Edit the class CSV file to update the student name (change "Margaret" to "Maggie" in this example):
Modifying class cs100f22
The following student names will be updated:
Hamilton, Margaret -> Hamilton, Maggie
Proceed? (Y/n) y
Students modified successfully
Example: Change the Email Address of a Student
Edit the class CSV file to update the student email address (change Ada's email to "alovelace@babbage.edu" in this example):
Modify the class enrollment and confirm the changes:
gkeep modify cs100f22 cs100f22.csv
The output will be:
Modifying class cs100f22
The following students will be added to the class:
Lovelace, Ada, alovelace@babbage.edu
The following students will be removed from the class:
Lovelace, Ada, alovelace@example.edu
Proceed? (Y/n) y
Students added successfully
Students removed successfully
A new account was created because git-keeper uses the email address to
identify the student.
Note
In this example, the new account on the git-keeper server will be
alovelace1 because the username alovelace is associated with the
alovelace@example.edu email address.
Class Status
Each class in git-keeper has a status, "open" or "closed." When created a
class is open, and it remains open until the faculty explicitly closes it.
To change the status of a class run the command
gkeep status <class_name> <status>
where <status> is open or closed. The system will respond with
Status updated successfully
When a class is open, the faculty member can publish assignments and the students can receive results.
When a class is closed, the faculty cannot upload or publish any new
assignments. If they run gkeep upload or gkeep publish on a closed course,
they will receive a message, "Class
If a student pushes to a repo associated with a closed course they will receive an email indicating that the course is closed:
Subject: [cs1] class is closed
You have pushed a submission for a class that is is closed.
Password Reset
If a student forgets their password, the faculty member can reset their password using
gkeep passwd <username>
Sample Password Reset Email
Hello Sharon,
Your git-keeper password has been reset to QzmPflFP
If you have any questions, please contact your instructor rather than responding to this email directly.
Assignments
What follows is a guide to creating, uploading, and publishing assignments and then fetching the students' submissions.
Assignment Structure
To create an assignment, first create a directory to contain the assignment. The name of the directory will be the name of the assignment.
assignment.cfg (optional)
The optional assignment.cfg file may be used to configure the
testing environment, time and memory limits, and
whether or not the results emails will use HTML. See
Testing Environments and
Assignment Configuration for more details.
base_code
Within the assignment directory there must be a directory named
base_code. The contents of this directory will be the initial contents of the
student's repository for the assignment. Put skeleton code, data files,
instructions, etc. in this directory.
Note
Git cannot track empty directories, so any empty directories within
base_code will not appear when a student clones the assignment
repository.
email.txt
There must also be a file named email.txt. The email that students receive
when a new assignment is published will always contain a clone URL, and the
contents of email.txt will be appended to the email after the
URL. email.txt may be empty.
tests
A directory named tests is also required, which must contain either a shell
script named action.sh or a Python script named action.py. The tests
directory also contains any other code and data files that you will use to test
student code.
When a student submits an assignment to the server it creates a temporary clone
of the student's repository and a temporary copy of the tests directory. With
the temporary tests directory as its working directory, the testing
environment then runs action.sh using bash or action.py using python3,
passing the action script the path to the temporary clone of the student's
directory.
Creating Action Scripts
For some assignments you can write all your tests in bash or Python and so the
only file you need in the tests directory is action.sh or action.py.
For other assignments you may wish to write your tests in another language or
to use a testing framework such as JUnit to test the student code. In that case
you can simply call your tests from action.sh.
Running Tests Locally
Before you upload the assignment, you can test your tests locally either using
the gkeep local_test command or by running your action script directly and
passing it the path a solution.
Using gkeep local_test
The gkeep local_test command takes an assignment directory and a solution
directory as arguments. It then makes copies of the assignment's tests
directory and the provided solution directory into a timestamped subdirectory
of local_testing within the assignment directory, creating local_testing
if necessary. The tests are then run. If you need to investigate any of the
output files that were created during testing, you can check within
local_testing.
It is useful to create a solution directory within the assignment directory
to use for testing. This command runs tests locally for an assignment
hw01-hello_world if we are in the assignment's parent directory and the
assignment directory contains a solution subdirectory:
gkeep local_test hw01-hello_world hw01-hello_world/solution
Example output is below. Note that only the output between BEGIN RESULTS and
END RESULTS will be emailed to the student.
Tests path:
/home/turing/cs100/hw01-hello_world/tests
Solution path:
/home/turing/cs100/hw01-hello_world/solution
Copies of these directories will be created in this testing directory:
/home/turing/cs100/hw01-hello_world/local_testing/2024-04-06T13-43-27.157582
Tests will be run directly locally and configured timeout and memory
limits will not be enforced. Be sure to try the tests on the server
before publishing.
Running tests...
Success!
----------------------- BEGIN RESULTS ------------------------
All tests passed, good job!
------------------------ END RESULTS -------------------------
If you need to inspect any output files, see /home/turing/cs100/hw01-hello_world/local_testing/2024-04-06T13-43-27.157582
If you would like to clean up testing directories in the future, use
--cleanup
Running Tests Manually
Alternatively you can run your tests manually by entering the tests directory
in the terminal and running action.sh or action.py, giving it the path to a
solution as a command line argument:
bash action.sh ../solution
or
python3 action.py ../solution
The output of the action script (both stdout and stderr) are placed in the email that the student receives as feedback.
Testing Environments
The testing environment for an assignment can be specified in the optional file
assignment.cfg within the assignment directory. If this file does not exist
for a given assignment, the assignment will use the default testing
environment. This will be firejail, unless specified otherwise in the
Server Configuration.
Host Environment
The host testing environment is straightforward, but less secure than the
other environment types, and requires that any dependencies for the tests be
installed on the server itself.
The git-keeper server creates a user named tester, and tests are run within a
temporary directory in /home/tester. The tester user cannot access any
other user home directories, but student code could potentially access other
files within the tester home directory, including files for other currently
running tests (if multiple threads are used for testing).
This environment may be specified by placing the following in assignment.cfg:
[tests]
env = host
Firejail Environment
This testing environment uses Firejail for
sandboxing. As with host environments, tests are run by the tester user
within a temporary directory in /home/tester, but firejail is used to limit
the process so that it can only access files within the temporary testing
directory. Dependencies for the tests must still be installed directly on the
server.
The firejail package may need to be explicitly installed on the server
before this environment can be used. It is available in the official
repositories for many Linux distributions, including Ubuntu.
By default, firejail is run with the following options:
--noprofile --quiet --private=/home/tester/<temporary testing directory>
This makes firejail ignore any default profiles that may be installed on the
server, supresses firejail output so that it is not included in the results
email, and sandboxes the tests within the testing directory.
To use the default Firejail options, place the following in assignment.cfg:
[tests]
env = firejail
Additional options may be specified using the append_args field. For example,
if you wish to prohibit any network activity and prevent the process from
writing any files larger than 100 KB, you could use the following:
[tests]
env = firejail
append_args = --net=none --rlimit-fsize=102400
These options will be used in addition to the default options. For a full list
of options available for firejail, see the
Firejail homepage or read through the man
page.
Docker Environment
Tests may be run in a Docker container, which can provide both sandboxing and encapsulation of dependencies.
TODO: setting up docker on the server
To use this environment, a Docker container image must be specified in
assignment.cfg. For example, to use our Python 3.10 container the following
may be used:
[tests]
env = docker
image = gitkeeper/git-keeper-tester:python3.10
The first time tests are run using a particular image, the server must download the image. This can take some time, so it is important to submit a test submission before publishing the assignment so that the image is downloaded to the server before students start submitting.
TODO: Describe and link to our Docker Hub images
When tests are run, the temporary testing directory is mounted as a volume
within the container at /git-keeper-testing, and the tests directory is at
/git-keeper-testing/tests. To create your own container images, you will need
to use the tests directory as the working directory, and set the command to
run either action.sh or action.py depending on your preference.
For example, here is a Dockerfile to build an image with Python 3.10 that can
be used with git-keeper:
FROM python:3.10-slim
WORKDIR /git-keeper-tester/tests
CMD ["bash", "action.sh"]
If you want to install additional Python packages within the container, use
RUN commands. For example, this installs the pytest and pytest-timeout
packages using pip:
FROM python:3.10-slim
RUN pip install pytest pytest-timeout
WORKDIR /git-keeper-tester/tests
CMD ["bash", "action.sh"]
TODO: Describe how to test the image locally
You can upload your images to Docker Hub, where they can then be accessed by the server. See the Docker Hub documentation for more information.
Example
Here is an example where the tests are written entirely in action.sh.
Let's say you want to create an assignment for which students will write a
Python program to print Hello, world!. You want them to write this program
in an initially empty file named hello_world.py and for them to receive
instructions by email.
You might create an assignment structure like this:
hw01-hello_world
├── assignment.cfg
├── base_code
│ └── hello_world.py
├── email.txt
├── solution
│ └── hello_world.py
└── tests
├── action.sh
└── expected_output.txt
base_code/hello_world.py can be an empty file which the students will receive
as their starting point, and into which they will place their code. email.txt
contains instructions for the assignment, solution/hello_world.py contains
your solution, and tests/expected_output.txt contains Hello, world!.
In assignment.cfg let's use firejail as the testing environment and set a 5
second timeout in case the student writes an infinite loop in their code:
[tests]
env = firejail
timeout = 5
What's left is to write action.sh. You want to run the student's
hello_world.py and compare the output to expected_output.txt. Here is a
simple way to go about it:
# The path to the student's submission directory is in $1
SUBMISSION_DIR=$1
# Run the student's code and put the output (stdout and stderr) in output.txt
python $SUBMISSION_DIR/hello_world.py &> output.txt
# Compare the output with the expected output. Throw away the diff output
# because we only care about diff's exit code
diff output.txt expected_output.txt &> /dev/null
# diff returns a non-zero exit code if the files were different
if [ $? -ne 0 ]
then
echo "Your program did not produce the expected output. Your output:"
echo
cat output.txt
echo
echo "Expected output:"
echo
cat expected_output.txt
else
echo "Tests passed, good job!"
fi
# Always exit 0. If action.sh exits with a non-zero exit code the server sees
# this as an error in your tests.
exit 0
Uploading an Assignment
Let's assume you have created an assignment named hw01-hello_world, as in the
example above, which is for the class CS100. You can upload the assignment to
the server like so:
gkeep upload CS100 hw01-hello_world
Uploading an assignment does not immediately send it to your students. If the
assignment uploads successfully you will receive an email that looks just like
the email that the students get when they receive the assignment. You can make
sure the assignment works as expected by using gkeep test or by cloning it
and pushing some solutions.
If you discover errors in your assignment you can update it before sending it to the students. You can modify any one of the four components of the assignment individually, or update everything. To update the entire assignment:
gkeep update CS100 hw01-hello_world all
Run gkeep update without additional arguments for more info.
Publishing an Assignment
Once you are satisfied with your uploaded assignment you can publish it, which will send it out to students:
gkeep publish CS100 hw01-hello_world
Once an assignment is published you cannot update the base code or the email, but you can update the tests.
Fetching Submissions
When you want to grade your students' submissions, you can fetch them with
gkeep fetch. If you defined submissions_path in the [local] section of
client.cfg then gkeep can fetch all your assignments into a common
directory. Otherwrise you need to specify a directory to fetch to.
This will fetch into submissions_path:
gkeep fetch CS100 hw01-hello_world
Fetch into the current directory:
gkeep fetch CS100 hw01-hello_world
The fetched directory for the assigment contains 2 subdirectories: reports
and submissions. reports contains the text of the emails that your students
received when they submitted. The submissions directory contains the code
that your students submitted.
Assignment Templates
You can use the command gkeep new to create the files and directories required for
an assignment. For example,
gkeep new homework1
will create a folder homework1 in the current directory with the following structure:
homework1
├── assignment.cfg
├── base_code
├── email.txt
└── tests
└── action.sh
where homework1, base_code, and tests are folders and assignment.cfg,
email.txt, and action.sh are empty files.
You can create your own assignment templates in
~/.config/git-keeper/templates and then provide a template name to
gkeep new to create an assignment from one of your templates. The new
assignment directory will simply be a copy of the template directory.
For example,
gkeep new function_examples inclass
Would create an assignment folder named function_examples using the template inclass.
This feature is useful when you have a standard assignment.cfg, email.txt, action.sh, or
other files.
You can change the location of the templates in client.cfg. In the [local] section, add
templates_path, which must be an absolute path. For example,
# ... other lines omitted
[local]
templates_path = ~/templates
Tutorials
The tutorials below will walk you through various scenarios.
Create your First Assignment
In this tutorial you will create, test, and publish a simple assignment for an existing class.
Prerequisites
- A working
git-keeperserver - A faculty account on the server
- The
gkeepclient setup on your computer - An active class in
git-keeper
Throughout the tutorial, we will use the class name cs100f22. You should use the name of
your existing class.
Create a Base Assignment from the Default Template
The easiest way to create an assignment is to use the gkeep new command, which will create
a directory containing empty copies of all the required files for an assignment. Use the following
command to create an assignment named hwk_even:
gkeep new hwk_even
An assignment in git-keeper is a folder where the name of the folder is the name of the assignment.
The folder contains:
base_code- a folder containing one or more files that will in thegitrepository of every studentemail.txt- a file containing any information you want to include with the clone url when the assignment is publishedassignment.cfg(optional) - a configuration file specifying system-level details of how each student submission will be testedtests- a folder containing any code and data used to test a student submissiontests/action.shORtests/action.py- a script that executes your tests
Prepare the Assignment
In this tutorial, we will create a simple CS1-level assignment in Python where students
must implement a function that determines if a number is even. The tests will use the built-in
unittest framework to execute tests on the assignment.
Base Code
Create a new file hwk_even/base_code/even.py:
def is_even(number):
return False
for number in range(10):
if is_even(number):
print('{} is even'.format(number))
else:
print('{} is odd'.format(number))
Tests
To test a student submission we will compare the output of the student submission and of a correct solution.
First, create a new file hwk_even/tests/expected.py containing the correct solution:
def is_even(number):
return number % 2 == 0
for number in range(10):
if is_even(number):
print('{} is even'.format(number))
else:
print('{} is odd'.format(number))
The git-keeper system runs action.sh to start the test process. Edit the file
hwk_even/tests/action.sh:
# Redirect stderr and stdout to a file
python3 $1/even.py > student_output.txt 2>&1
# If python has a non-zero exit code, something went wrong running the student code
if [ $? -ne 0 ]; then
echo "There was an error when running your code:"
echo "-------------------------------------------------"
cat student_output.txt
echo "-------------------------------------------------"
echo "Please try again"
exit 0
fi
# Redirect output of a correct solution
python3 expected.py > expected_output.txt
# Compare the student output with the correcdt output
# Send output to /dev/null because we don't need it
diff -w student_output.txt expected_output.txt >> /dev/null
# diff returns non-zero when the files are not the same
if [ $? -ne 0 ]; then
echo "Your output is not correct. Expected:"
cat expected_output.txt
echo "Your output:"
cat student_output.txt
exit 0
fi
echo "Your output is correct. Nice work!"
cat student_output.txt
# Any non-zero exit code indicates a problem with the test process
# Make sure to have the following line at the end of all action.sh files
exit 0
Email Announcement
The contents of hwk_even/email.txt will be used in the assignment announcement email
sent to all students. Edit this file to contain:
hwk_even: Implement a function to determine if a number is even.
HINT: Use the modulus operator!
Assignment Configuration
An empty file assignment.cfg was created by gkeep new, but we do not need to edit it
for this assignment. All possible values in this file are optional, and by leaving it
empty the server will use default values.
Upload the Assignment
Now that we have all the files prepared for the assignment, we can upload it to the server.
In the parent directory of hwk_even, run:
gkeep upload cs100f22 hwk_even
The output should be
uploading hwk_even in cs100f22
Assignment uploaded successfully
In addition, you should have an email from git-keeper containing:
Clone URL:
ssh://prof1@gkserver/home/prof1/prof1/cs100f22/hwk_even.git
hwk_even: Implement a function to determine if a number is even.
HINT: Use the modulus operator!
NOTE: You will see your username in place of prof1 in the clone URL.
Test the Assignment
At this point the assignment is on the server, but it is NOT distributed to the students. Before we publish the assignment, let's test it to make sure the test process works as expected.
We will use the gkeep test command to simulate the process of a student pushing their code to
their repo.
First we will submit a copy of the correct solution. Create a folder named solution in
hwk_even and then edit the file hwk_even/solution/even.py:
def is_even(number):
return number % 2 == 0
for number in range(10):
if is_even(number):
print('{} is even'.format(number))
else:
print('{} is odd'.format(number))
Now run the tests on this solution:
gkeep test cs100f22 hwk_even hwk_even/solution
The output should be:
Testing solution hwk_even/solution for assignment hwk_even in class cs100f22
Pushing your solution using git
Solution pushed successfully, you should receive a report via email
You should receive an email containing:
Your output is correct. Nice work!
0 is even
1 is odd
2 is even
3 is odd
4 is even
5 is odd
6 is even
7 is odd
8 is even
9 is odd
Next we will submit an incorrect solution:
gkeep test cs100f22 hwk_even hwk_even/base_code
The output should be:
Testing solution hwk_even/base_code for assignment hwk_even in class cs100f22
Pushing your solution using git
Solution pushed successfully, you should receive a report via email
The email from git-keeper should be:
Your output is not correct. Expected:
0 is even
1 is odd
2 is even
3 is odd
4 is even
5 is odd
6 is even
7 is odd
8 is even
9 is odd
Your output:
0 is odd
1 is odd
2 is odd
3 is odd
4 is odd
5 is odd
6 is odd
7 is odd
8 is odd
9 is odd
Finally, let's submit code that throws an exception. Create a folder hwk_even/bad_code
and then edit the file hwk_even/bad_code/even.py:
def is_even(number):
return 0/0
for number in range(10):
if is_even(number):
print('{} is even'.format(number))
else:
print('{} is odd'.format(number))
The output should be:
Testing solution hwk_even/bad_code for assignment hwk_even in class cs100f22
Pushing your solution using git
Solution pushed successfully, you should receive a report via email
The email from git-keeper should be:
There was an error when running your code:
-------------------------------------------------
Traceback (most recent call last):
File "/home/tester/hwk_even/even.py", line 7, in <module>
if is_even(number):
File "/home/tester/hwk_even/even.py", line 2, in is_even
return 0/0
ZeroDivisionError: division by zero
-------------------------------------------------
Please try again
Publish the Assignment
At this point we have demonstrated that our submission testing handles correct solutions as well as solutions that produce incorrect output or produce an error. We are ready to publish the assignment:
gkeep publish cs100f22 hwk_even
The output should be:
Publishing assignment hwk_even in class cs100f22
Assignment successfully published
Each student will receive an announcement email:
Clone URL:
ssh://alovelace@gkserver/home/alovelace/prof1/cs100f22/hwk_even.git
hwk_even: Implement a function to determine if a number is even.
HINT: Use the modulus operator!
A Simple Assignment From the Default Template
In this tutorial you will create a simple assignment and upload it to
the git-keeper server.
Prerequisites
- A working
git-keeperserver - A faculty account on the server
- The
gkeepclient setup on your computer - A class named
cs100f22added to the server
Overview
The gkeep new is a fast way to create the required files and directory
structure for an assignment.
Use the gkeep new command to create an assignment named project1.
gkeep new project1
Edit project1/base_code/proj1.py:
def is_valid(username):
return False
Edit project1/email.txt:
Your first project. See Canvas for details.
Edit project1/tests/action.sh:
echo "Your submission was received"
exit 0
Upload the assignment:
gkeep upload cs100f22 project1
The output should be:
uploading project1 in cs100f22
Assignment uploaded successfully
And you should have an email containing:
Clone URL:
ssh://prof1@gkserver/home/prof1/prof1/cs100f22/project1.git
Your first project. See Canvas for details.
(where prof1 is your username on the git-keeper server).
Use an Assignment Template
In this tutorial you will create a template and then use it to create a new assignment.
Prerequisites
- A working
git-keeperserver - A faculty account on the server
- The
gkeepclient setup on your computer
Overview
The gkeep new command is used to create a new assignment. By default, the command creates
the required directories and files for a valid assignment, and then the faculty member modifies
things to create the assignment. But gkeep new can also create an assignment from a template.
This is useful, for example, when you have a common test mechanism for a course.
A template has the same structure as an assignment, but all files are optional:
<template_name>
├── assignment.cfg
├── base_code
├── email.txt
└── tests
└── action.sh
By default, gkeep new will look in ~/.config/git-keeper/templates for templates unless
the ~/.config/git-keeper/client.cfg file contains
[local]
template_path = <absolute path>
in which case gkeep new will look in <absolute path>.
Create a Template
Faculty often use git-keeper to distribute code for in-class examples. In this case, the
email announcement is typically minimal, and we do not expect students to submit a solution.
We can create an assignment template containing an email.txt with the default message
and an action.sh that simply reminds students they do not need to submit.
Start by using gkeep new to create a default template within ~/.config/git-keeper/templates
in a folder named inclass:
gkeep new ~/.config/git-keeper/templates/inclass
Edit the file ~/.config/git-keeper/templates/inclass/email.txt to contain a message
such as the following:
This repo contains an in-class example.
Edit the file ~/.config/git-keeper/templates/inclass/tests/action.sh such that it reminds
students they do not need to submit:
echo 'No need to push in-class examples.'
exit 0
Edit the file ~/.config/git-keeper/templates/inclass/assignment.cfg so that the subject
of the announcement email for any example created from this template will indicate it is an
in-class example. Git-keeper will replace {class_name} and {assignment_name} in the
subject template with the class and assignment names, so this configuration will work for any
class and assignment:
[email]
announcement_subject = [{class_name}] New in-class example: {assignment_name}
Use the template
Go to a directory where you want to create an assignment and then run:
gkeep new example1 inclass
The system will create a folder named example1 that contains the files in
~/.config/git-keeper/templates/inclass. You can add your code to base_code
and then upload and publish the assignment.
Update an Assignment
In this tutorial, you will update an existing assignment.
Prerequisites
- A working
git-keeperserver - A faculty account on the server
- The
gkeepclient setup on your computer - A class named
cs100f22added to the server - The
project1example assignment created and uploaded (but not published)**
Overview
The gkeep update command is used to modify an existing assignment. Before an assignment is
published, gkeep update can be used to modify any aspect of an assignment (base code, email,
tests, configuration). Once an assignment is published, each student has a copy of the base code
repo and has received the announcement email, and therefore only the tests and configuration
may be changed with gkeep update.
Example: Update the Email Before Publish
Edit project1/email.txt:
Your first project is to implement a function to validate
a username. See Canvas for details.
Update the assignment:
gkeep update cs100f22 project1 email
The output should be:
updating project1 in cs100f22
Assignment updated successfully
And you should have an email containing:
Clone URL:
ssh://prof1@gkserver/home/prof1/prof1/cs100f22/project1.git
Your first project is to implement a function to validate
a username. See Canvas for details.
Example: Update Base Code Before Publish
Edit project1/base_code/proj1.py:
def is_valid(username):
"""
A username is valid if it contains only lowercase
letters, numbers, and the underscore character.
In addition, it must start with a letter.
"""
return False
Update the assignment:
gkeep update cs100f22 project1 base_code
The output should be:
updating project1 in cs100f22
Assignment updated successfully
And you should have an email containing:
Clone URL:
ssh://prof1@gkserver/home/prof1/prof1/cs100f22/project1.git
Your first project is to implement a function to validate
a username. See Canvas for details.
In addition, if you clone the repo you will find a single commit that contains the base code. This ensures that students only see the final version of the assignment when they clone the repo.
Other Updates
Before you publish an assignment, you can update the tests or config
in a similar way to the previous examples.
If you need to update multiple aspects of an assignment, modify all the files and then run
gkeep update cs100f22 project1 all
Example: Base Code Cannot be Updated After Publish
First, publish the assignment
gkeep publish cs100f22 project1
The output should be:
Publishing assignment project1 in class cs100f22
Assignment successfully published
Now edit project1/base_code:
# Name:
def is_valid(username):
"""
A username is valid if it contains only lowercase
letters, numbers, and the underscore character.
In addition, it must start with a letter.
"""
return False
And attempt to update:
gkeep update cs100f22 project1 base_code
The output should be:
Assignment is already published, only tests or config may be updated.
You cannot update the base code of an assignment after it is published. The publish
action creates a copy of the repo in each student's account, and they may have cloned
their repo. Making a change to the student repo now could lead to git merge
conflicts.
If you publish an assignment and later have to change the code, you will have to
distribute these changes outside of git-keeper (for example, post an announcement
on your LMS).
Example: Update Tests After Publish
Edit project1/tests/test_proj1.py:
from proj1 import is_valid
def verify_result(case, expected):
result = is_valid(case)
if result == expected:
print('GOOD: is_valid({}) returns {}'.format(case, expected))
else:
print('ERROR: is_valid({}) should return {}'.format(case, expected))
print('Here are the results from a few test cases:')
verify_result('username', True)
verify_result('Username', False)
verify_result('user_name', True)
verify_result('_username', False)
print('"GOOD" for all cases does not guarantee a correct solution.')
print('When grading I will test additional cases!')
Edit project1/tests/action.sh:
export PYTHONPATH=$1
python3 test_proj1.py
exit 0
Update the assignment:
gkeep update cs100f22 project2 tests
The output should be:
updating project2 in cs100f22
Assignment updated successfully
Keep in mind that students may have already submitted, and git-keeper WILL NOT
automatically rerun tests. You can use the gkeep trigger command to manually run
tests.
Trigger Tests for One or More Students
In this tutorial you will trigger tests for one or more students.
Prerequisites
- A working
git-keeperserver - A faculty account on the server
- The
gkeepclient setup on your computer - A class named
cs100f22added to the server - The
project1example assignment created, uploaded, and published
Overview
The gkeep trigger command causes the action.sh or action.py script of an assignment
to be executed for the current repos of one or more students. This is useful if a
student deletes the git-keeper response email or if you change the tests for an
assignment after it is published.
Trigger Tests For the Entire Class
To trigger tests for all students in the class:
gkeep trigger cs100f22 project1
The output will ask for confirmation:
Triggering tests for project1 in class cs100f22 for the following students:
mhamilton
ghopper
alovelace
Proceed? (Y/n) y
Tests triggered successfully
The action.sh will run with each student's repo regardless of whether they have pushed
changes.
Trigger Tests for a Subset of Students
To trigger the tests for a subset of students
gkeep trigger cs100f22 project1 ghopper alovelace
The output will ask for confirmation:
Triggering tests for project1 in class cs100f22 for the following students:
ghopper
alovelace
Proceed? (Y/n) y
Tests triggered successfully
Delete or Disable an Assignment
In this tutorial, you will delete an unpublished assignment and disable a published assignment.
Prerequisites
- A working
git-keeperserver - A faculty account on the server
- The
gkeepclient setup on your computer - A class named
cs100f22added to the server - The
project1example assignment created and uploaded (but not published)
Overview
Before you publish an assignment, it is safe to delete it from the server because it only exists in your account. After you publish an assignment, you can no longer delete it because each student in the class has a copy of the repo (and they may have already cloned that repo). In this case your only option is to disable the assignment.
Example: Delete an Unpublished Assignment
At this point, the project1 assignment is uploaded but not published. The repo exists
in your faculty account, but it has not been copied to the students' accounts. Therefore,
it is safe to delete the assignment:
gkeep delete cs100f22 project1
The output asks for confirmation:
Deleting assignment project3 in class cs100f22
Proceed? (Y/n) y
Assignment deleted successfully
Example: Disable a Published Assignment
If you completed the first example, re-upload the assignment:
gkeep upload cs100f22 project3
The output should be:
uploading project3 in cs100f22
Assignment uploaded successfully
Regardless of whether you completed the previous example, publish the assignment:
gkeep publish cs100f22 project1
The output should be:
Publishing assignment project3 in class cs100f22
Assignment successfully published
Now try to delete the assignment:
gkeep delete cs100f22 project1
The output should be:
Assignment project1 is published and cannot be deleted.
Use gkeep disable if you wish to disable this assignment.
You cannot delete a published assignment because the students already received their announcement emails, and they may have cloned the assignment.
Instead, you must disable the assignment:
gkeep disable cs100f22 project1
The output asks for confirmation:
Disabling assignment projet1 in class cs100f22. This cannot be undone.
Students will be notified that the assignment has been disabled.
The action.sh/action.py script will no longer be run on submissions
to this assignment. Instead, students will receive an email stating
that the assignment is disabled.
Proceed? (Y/n) y
Assignment disabled successfully
The students in the class receive an email:
Assignment project1 in class cs100f22 has been disabled. No tests will be run if you push to your repository for this assignment.
If the student pushes to the repo, they will receive an email:
Assignment project1 in class cs100f22 has been disabled.