Template for grader image builders for python assignments
- To provide a template for creating a grader image for python assignments
- To automate the programming assignment grading process so that educators can focus more on teaching
- Fork this repository.
- Go to the
Settingstab of your repository and click onActionson the left sidebar.- Click on
Generaland go toWorkflow permissions. - Choose
Read and write permissionsand Save.
- Click on
- Edit
tests/test_syntax.pyto set allowed modules and functions. - Customize
tests/test_results.pyto define the expected results. - Push to GitHub :
build.ymlbuilds your image and pushes to GHCR (GitHub Container Repository).
script_pathfixture will be available if your test script in thetests/folder importspytest.- Currently
requirements.txtis for documentation purpose.
build.yml: Builds and pushes a multi-arch grader image to GHCR.- Uses GHCR for privacy and GitHub integration—swap to Docker Hub by updating
registryandtagsif preferred. - Requires
Dockerfilein repo root (see Dockerfile reference). SetBUILDER_PATin secrets for optional dispatch.
- Builds a lightweight grader image with
pytest. - Installs dependencies from
requirements.txt. - Customize
CMDto run your tests (e.g.,python3 -m pytest tests/).
This is the grader template — the instructor-facing half of a two-repo pattern:
- This repo (grader) — you customize the test files, push, and GitHub Actions builds a Docker image containing your tests. The image is published to GHCR.
- python-homework-template (student-facing) — contains
exercise.pyand aclassroom.ymlworkflow. When a student pushes,classroom.ymlpulls your grader image and runs the tests.
This repo uses secrets.GITHUB_TOKEN (automatically provided by GitHub Actions) to:
- Log in to GHCR and push the grader Docker image
- Pass as
GIT_AUTH_TOKENduring Docker build for cloning dependencies
No manual token setup is needed, but you must enable write access:
Settings > Actions > General > Workflow permissions > "Read and write permissions"
Without this, the Docker image push will fail with a 403 error.
| File | What to Change |
|---|---|
tests/test_syntax.py |
Set allowed_modules and ALLOWED_FUNCTIONS for the assignment |
tests/test_style.py |
Usually no changes needed (checks PEP 8 style) |
tests/test_results.py |
Define expected inputs/outputs for the assignment |
tests/conftest.py |
Usually no changes needed (provides script_path fixture) |
After your grader image builds (check the Actions tab), note the image URL:
ghcr.io/{your-username}/{this-repo-name}:latest
In the student homework repository, set this as a repository variable:
Settings > Secrets and variables > Actions > Variables
Variable name: PYTHON_GRADER_??? (replace ??? with the assignment identifier, e.g., PYTHON_GRADER_301)
Value: ghcr.io/{your-username}/{this-repo-name}:latest
The following secrets are set on the homework template side (or as organization secrets):
A GitHub fine-grained Personal Access Token that allows the homework repo's workflow to pull the grader image from GHCR.
- Go to GitHub > Settings (user) > Developer settings > Personal access tokens > Fine-grained tokens.
- Click Generate new token.
- Set the following permission:
| Permission | Access | Purpose |
|---|---|---|
| Packages | Read | Pull grader Docker images from GHCR |
- Save as a secret named
CR_PATin the homework repo or organization.
GITHUB_TOKENcannot be used for this because it is scoped to the current repo and cannot read packages from a different repo.
These power the AI tutor feedback step in the homework repo. At least one must be set.
| Secret Name | Service | Where to Obtain |
|---|---|---|
CLAUDE_API_KEY |
Anthropic Claude | https://console.anthropic.com/ |
GOOGLE_API_KEY |
Google Gemini | https://aistudio.google.com/ |
XAI_API_KEY |
xAI Grok | https://console.x.ai/ |
NVIDIA_NIM_API_KEY |
NVIDIA NIM | https://build.nvidia.com/ |
PERPLEXITY_API_KEY |
Perplexity | https://perplexity.ai/settings/api |
Specifies the preferred LLM model. If unset, the AI tutor defaults to Gemini or uses whichever single key is available.
- This template is registered as a part of #C-2025-016393 in the Korea Copyright Commission.