-
Notifications
You must be signed in to change notification settings - Fork 26
Assignment Templates
An assignment's starter code is a normal GitHub repository with the Template
repository flag turned on. gh student accept creates a fresh private copy
for each student; gh student submit re-fetches a couple of files from it on
every submission. This page describes the expected layout.
Note
Templates are optional. An assignment without a template gives each student an initialized repository with a README and the autograding setup — good for write-from-scratch or short-answer work. See Repository shapes for every option. The rest of this page applies to assignments that ship a template.
A worked example lives at
templates/example-assignment/.
What accept creates is a per-assignment choice. All five shapes:
| Shape | Set with | Students get | Autogrades? |
|---|---|---|---|
| Template |
--template (or the web form's template field) |
A copy of the template plus the control files | Yes |
| Template, own CI |
no_autograder: true (web: Do not use the built-in autograder) |
A copy of the template with no autograding workflow; the template's own CI runs instead | No scores, but collection still records who submitted |
| Template-less with a README | Omit --template (web: No template, Add a README on) |
An initialized repository: README plus the control files | Yes |
| Template-less, no README |
init_shim: true (web: No template, Add a README off, built-in autograder on) |
An initialized repository carrying only the control files | Yes |
| Empty repository |
--empty-repo (web: No template, Add a README off, Do not use the built-in autograder) |
A completely bare repository: no commits, no control files, and no feedback pull request, ever | Never |
Two rules apply across all of them:
- Shape changes affect future accepts only. Every shape can be changed after creation, but repositories students already accepted keep their original setup; nothing is retrofitted. (Assignment type — individual or group — is the exception: it stays locked once set.)
-
A template brings only its default branch unless the assignment turns
on Include all branches (
include_all_branches: true), which copies every branch into each generated repository. Template-only; it has no effect on the other shapes. A specific source branch can't be chosen: GitHub's create-from-template API has no branch parameter, so a@branchsuffix on the CLI's--templateis ignored with a warning. To start students from a different branch, change the template repository's default branch.
For the flag-level details (mutual exclusions and assignments.json fields),
see gh teacher assignment add.
.
├── README.md # student-facing assignment description
├── .gitignore # optional, re-fetched on every gh student submit
├── .github/ # optional, re-fetched on every gh student submit
│ └── workflows/ # CI for student copies (NOT autograde — see below)
├── pull_request_template.md # optional, can drive the Feedback PR body
└── <starter code> # whatever files the assignment needs
-
README.md— what the student sees on their copy. Describe the assignment, expected output, and evaluation criteria. -
.gitignore(optional) — re-fetched from the template on every submit, so updating it once propagates to every student's next submission. -
.github/(optional) — same re-fetch behavior. Put non-autograde workflows here (linters, formatters, dependabot). -
pull_request_template.md(optional) — GitHub's native pull request template (.github/pull_request_template.md, root, ordocs/). If the assignment enables Use the template's pull request template as the Feedback PR body, Classroom 50 uses this file's contents as each student's Feedback PR body instead of the built-in text. See Autograders. - Starter code — any files the student starts from, from a single file to a full project.
Warning
Never put .github/workflows/autograde.yaml in the template. The autograde
shim is written by gh student accept (it's embedded in gh-student) and
never changes after accept. A copy in the template would be clobbered by
submit's .github/ re-fetch and double-grade or break grading. Autograding
logic lives in your classroom50 repository, not the template — see Autograding Basics.
-
Create a repository with the structure above, then register it:
gh teacher assignment add <org> <classroom> <slug> --name "…" --template <owner>/<repo>
The assignment slug (e.g.,
hello) is what students pass togh student accept; it needn't match the repository name. -
Set visibility (see below).
-
Mark it as a template in Settings → General → Template repository.
Students can then run:
gh student accept <org> <classroom> <slug>…which creates <org>/<classroom>-<slug>-<username> (lowercased) from your
template.
A public template always works. A private template works only if it's inside your organization — registering the assignment grants the classroom's team read access to it. A private template outside your organization is rejected (students can't be granted access, so accept would 404). Enterprise Cloud's "internal" visibility also works.
Note
The team read grant happens when you create the assignment. If you create the assignment first and add a private template later by editing it, the grant isn't re-applied and students may get a 404 on accept.
- The template must have at least one commit. A freshly created, commitless repository is rejected when you register the assignment — GitHub can't generate a copy of nothing. (A brand-new template with real commits can briefly be misreported by GitHub right after a push; if a just-pushed template is rejected, wait a minute and retry.)
- Forked templates can trip other orgs' OAuth restrictions. With a template that is a fork of a repository in a different organization, GitHub evaluates OAuth-app access restrictions against the fork's parent organization too — accept can fail with an HTTP 403 naming OAuth App access restrictions even though your own org has approved Classroom 50. Either have the upstream organization approve Classroom 50 as well, or (simpler) copy the content into a fresh, fork-free repository in your organization and flag that as the template.
-
Only the default branch is copied unless the assignment enables
Include all branches (
include_all_branches), which passes every branch through to each generated student repo. -
GitHub's template-generate copies files, not settings. Classroom 50
compensates at accept time:
- The About description and topics are copied when the assignment's
Copy About from template / Copy topics from template toggles are on
(the default for new assignments). This runs on the web accept path; a
student who accepts with
gh student acceptgets the repository without them. - Repository features (Issues, Wiki, Projects, Pull requests) follow the assignment's Repository features settings — by default each inherits the template's current setting; you can force any of them on or off per assignment. This applies on both the web and CLI accept paths. Repos accepted before a change can be updated with the submissions page's Update repository features action.
- The About description and topics are copied when the assignment's
Copy About from template / Copy topics from template toggles are on
(the default for new assignments). This runs on the web accept path; a
student who accepts with
The same repository can be the template for any number of assignments — each accept generates an independent copy of the template as it exists at that moment. That makes an evolving course repository workable: register assignment A, keep committing, register assignment B later from the same repo. Two things to keep in mind:
- Students who accept the same assignment at different times can start from different template states — late accepters get the newer content. Freeze the template (or cut a dedicated template repo per assignment) if identical starting points matter.
-
.gitignoreand.github/are re-fetched from the template on every submit (see below), so changes to those files propagate to every assignment that shares the template.
On every submission, gh student submit re-fetches .gitignore and .github/
from the template (recorded in .classroom50.yaml). Starter code and the README
are not re-fetched — they belong to the student once accepted. Runtime,
dependency, and grading-logic changes propagate separately, through the runner
workflow and assignments.json, which the runner fetches fresh on every
submission.
- Start here
- Teacher guides
- Autograding
- Students
- Reference