Lucy assumes that when a student forks an assignment template, the course’s marker user can immediately see that fork. Nothing in Lucy makes that happen, and nothing inside your course’s GitLab group shows you how it happens — there is no project or group webhook to look at. It is done by a file hook running on the GitLab server itself, maintained by the SoCo Facilities Team.
This page records what that hook does, because it is load-bearing for every
course and is otherwise invisible from inside a project. (Thanks to the
Facilities Team for the explanation; see lucy/lucy#185.)
What the hook is#
A locally developed GitLab plugin runs on the servers as a
file hook. The code
(cecslabs/gitlab-teaching-plugin) and its configuration
(cecsit/gitlab-plugin) live in private repos on
gitlab.comp.anu.edu.au, with documentation
on the SoCo Facilities wiki.
What it does#
Forks are made private, always. This applies instance-wide to every fork, not just to course templates, and is not something you configure per course. Note that a student can undo it by hand.
Per-repository, if configured, forking also:
- adds one or more users at a specified access level — usually a dedicated marker user as Maintainer (access level 40), though course staff’s own accounts have been used too;
- adds one or more webhooks; and/or
- copies issues from the forked repository.
Only the “add user” behaviour has been used in the last couple of years.
The two behaviours work together, and the order matters for understanding
what you see: an internal template forked into a student’s personal
namespace comes out private, so the marker cannot see it at all. What
makes marking work is the membership the hook grants, not the visibility. A
real course’s forks look like comp3900/2026: an internal template, private
student forks, and the marker a member of each fork at access level 40.
So the fix for an unreachable fork is membership, not visibility. Making forks internal also works, but it is not the path production takes.
Requesting one#
Email the SoCo Facilities Team to request a fork hook for your assignment templates, and a marker account if you do not already have one. Do this before your first assignment template is forked — the hook fires on fork, so it does nothing for forks that already exist.
When it doesn’t fire#
If the hook fails to fire for a student, Lucy reports no fork exists for
someone who has obviously submitted, and nothing in that message points at
access as the cause. Lucy is not lying: as the marker, the student’s private
fork genuinely 404s.
Check membership on the fork first. Look at the student’s project as the marker user; if the marker is not a member, ask the student to add them as a Maintainer, or have Facilities re-run the hook.
Two related GitLab behaviours#
Neither of these is caused by the hook, but both surface in the same area and both cost us time to work out.
A fork keeps changing after it reports finished. The import continues
writing to the project for a second or two after import_status reads
finished, and anything you set on a fresh fork in that window —
visibility, membership — can be silently reverted. Code that touches a
just-created fork needs to confirm the change stuck, more than once, rather
than trusting the first success. In the live test suite this showed up as
roughly one fork per run quietly losing its setting, with a different student
affected each time; see grant_marker_access in
lucy/tests/live/backend.py.
Project deletion is delayed. In recent GitLab versions (17.x and later) a
plain DELETE only marks a project for deletion: it is renamed to
<path>-deletion_scheduled-<id> and stays in the namespace. This is standard
GitLab, not a local customisation. Removing it properly takes a second delete
with permanently_remove=True — otherwise cleanup code leaves junk behind
forever, which matters for the test accounts and for any tooling that creates
and destroys projects in a loop.