How to add an exercise
What is an exercise?
Exercises are graded Git challenges that students complete independently to demonstrate their understanding of Git concepts. Unlike hands-ons, which only set up a sandbox for a lesson, exercises have a full lifecycle: the app downloads a starting repository state, the student performs the required Git operations, and the app verifies their work against a grading script.
For example, a student can run gitmastery download branch-bender to receive a repository in a specific state, then work through the challenge before running gitmastery verify branch-bender to get feedback.
Each exercise consists of two main components:
download.py— sets up the initial repository state the student works from.verify.py— inspects the student’s repository after they attempt the exercise and returns a pass or fail result with feedback.
Some examples of how Git-Mastery app uses exercises can be found here.
Before contributing
If you are proposing a new exercise, instead of implementing an already approved exercise proposal, make sure that you have done the following:
- Create an exercise discussion
- Obtain approval on the exercise
- File a remote repository request (if needed)
Create a new exercise
Use the provided new.sh script to generate the scaffolding for a new exercise:
./new.sh
The script will first prompt if you want to create a hands-on or exercise.
Enter e to create a new exercise.
Then, the script will prompt you for:
- The name of the exercise, likely specified in the corresponding exercise discussion. Use kebab case.
- The exercise tags, split by spaces, likely specified in the corresponding exercise discussion.
- The exercise repository type. The scaffold currently supports
local,remote, andignoredirectly.
Refer to the Exercise format reference page for more information about the generated folder structure and repository type options.
Download setup
download.py contains the instructions to set up the local repository.
The app loads download.py dynamically from the exercises source, reads __resources__ if present, and executes setup(...) inside the student’s working repository.
For more information about how Git-Mastery downloads exercises, refer to the Download flow.
exercisescomes with a set of utility functions in theexercise_utilsmodule that are made available during the download flow. Prefer these abstractions over raw CLI calls — for example, useexercise_utils.file.create_or_update_fileto create or update files, andexercise_utils.git.committo commit changes. Fall back toexercise_utils.cli.run_commandonly when no suitable abstraction exists.For the full list of utility functions, refer to Exercise utilities reference.
These are some references for download setups for other exercises:
Download conventions
- Any operations should use OS-agnostic options, for example
shutil.rmtreeinstead ofrun_command(["rm"]). - If you need to compare repository state before and after the student’s work, create the start tag during setup using the shared Git-Mastery utilities.
- For any commands that require
gh, make sure that therequires_githubconfiguration is set totrueso that the app automatically checks that the student has set up GitHub CLI correctly. setup(...)may receive arepo-smithhelper object asrs; use it instead of shelling out directly when possible.
Verification setup
The verification process is controlled by verify.py. This file contains the grading logic that inspects the student’s work and returns a result with a status and feedback comments.
For more information about how Git-Mastery verifies exercise attempts, refer to the Verification flow.
The git-autograder library builds the GitAutograderExercise object passed to verify(...). It exposes the exercise config, the working repository, and optional answer parsing.
If there is no helper for a check you need, you can still fall back to the underlying GitPython repository (however, this should be avoided):
from git_autograder import (
GitAutograderExercise,
GitAutograderOutput,
GitAutograderStatus,
)
def verify(exercise: GitAutograderExercise) -> GitAutograderOutput:
repo = exercise.repo
return exercise.to_output([], GitAutograderStatus.SUCCESSFUL)
Refer to existing verify.py scripts to understand the available helper functions that streamline grading. Open an issue if there is something that is not yet supported or if you have a question.
For repo_type: ignore exercises, exercise.repo is a null repository wrapper. In that mode, verify against files such as answers.txt or exercise metadata rather than Git state.
Some examples of verifications:
Verification conventions
- Store the comments of the verification as constants so that they can be imported and used reliably in unit tests.
- For any remote behavior to verify, provide a mock to substitute the behavior in unit tests.
- Prefer raising
exercise.wrong_answer([...])for incorrect submissions and reserve unexpected exceptions for genuine errors.
Testing
Testing downloads without app
To test that your download script works locally without the app, use the provided script:
./test-download.sh <exercise name>
You can find the sandbox created by the script under test-downloads/. Check it manually to verify that it is as expected.
Testing verify logic without app
Use repo-smith to simulate possible student answers and verify that your grading logic correctly accepts valid attempts and flags expected mistakes.
Refer to existing test_verify.py files to see examples of unit testing the verification script.
See Testing guide for the recommended GitAutograderTestLoader workflow.
You can run the unit tests of your exercise via:
./test.sh <your exercise folder>
Testing downloads and verify using app
To test the full student workflow, push your changes to a branch in a repository and modify the .gitmastery.json file in your gitmastery-exercises directory such that exercises_source points to this branch.
{
"type": "remote",
"username": "your-github-username",
"repository": "your-repository-name",
"branch": "your-branch-name"
}
Run gitmastery download <your-exercise-name>. Check that the download is correct manually. Navigate into the exercise folder and run gitmastery verify. This should cause a failure as the exercise has not been complicated. Manually simulate a student’s workflow within the exercise folder (both correct and incorrect outputs) and run gitmastery verify to ensure your verification logic correctly grades these scenarios.
This will cause all subsequent gitmastery download and gitmastery verify commands run within this folder to pull exercises from your branch. After you are done testing, revert your .gitmastery.json file to its default state, where exercises_source is set to the Git-Mastery organisation repository.
Submitting the exercise for review
Create a pull request from your fork using the provided pull request template.
Example
- Exercise discussion: https://github.com/git-mastery/exercises/issues/24
- Remote repository request: https://github.com/git-mastery/exercises/issues/25
- Exercise PR: https://github.com/git-mastery/exercises/pull/26