The Push at 23:40 Before Open Night
Three Transition Year students have four weeks to ship an attendance app for 620 students. The stack is Python/Flask, SQLite and Bootstrap, hosted on a Raspberry Pi in the staff room, with the code in a shared GitHub repository. At 23:40 the night before Open Night, Aoife - the strongest coder - pushes three commits straight to main. The first adds a year_group column through a migration script. The second edits a template. The third is a half-finished refactor of the login route. She never pushes the matching model change. The Pi runs a timer that pulls main every five minutes, so by 08:15 the app dies on startup with no such column: year_group, and the demo is at 19:00. The other two students have uncommitted work on their laptops. Separately, the group generated student badges with a QR library licensed GPL-3.0, and a neighbouring school has now asked for a copy of the whole app.
1. It is 08:20 and the demo is at 19:00. Set out, in order, what the team should do to get a working build onto the Pi, and name one thing they must not do, with the reason.
Read the worked answer
1. Stop the bleeding. SSH into the Pi and disable the five-minute pull (systemctl stop attend-pull.timer or comment out the cron line). Without this, every fix is overwritten by the next pull and you will be debugging a moving target.
2. Find the last good state. git fetch, then git log --oneline on main. The commit immediately before Aoife's three is the candidate. Prove it: check it out locally and start the app. It should boot, because nothing in it referenced year_group.
3. Deploy a hotfix branch, not main. git checkout -b hotfix/open-night <good-commit>, push, and point the Pi's pull at that branch. This gets a demo build in minutes without disturbing the branch the other two students depend on.
4. Fix forward only if time allows. Add the missing model column and migration together on the hotfix branch, run it against a copy of the SQLite file first, then merge.
5. Recover the others' work. They commit to their own branches and open pull requests against the hotfix.
Must not: git push --force a rewritten main, or git reset --hard on the shared branch. That removes Aoife's commits from everyone else's history, breaks the other two students' local repositories, and turns a ten-minute revert into an afternoon of manual recovery. git revert writes new commits and is safe on shared history.
2. Recommend three process changes for the class's next project. For each, state precisely which part of this incident it would have prevented.
Read the worked answer
1. Protect main and require a pull request with one reviewer. Aoife pushed three commits at 23:40 with nobody looking. A required review would have put a second pair of eyes on the half-finished login refactor, and the reviewer's first question - "where is the model change?" - is exactly the bug. Branch protection is a setting, not a skill, so it costs nothing to adopt.
2. A smoke test in CI that boots the app and requests /login. The failure was a startup crash, not a subtle logic bug, so the cheapest possible test catches it. The rule that matters is that the build runs on every push to a branch, before merge, not on the Pi after merge. This would have blocked all three commits at the pull request stage.
3. Deploy tagged releases, not the tip of main. The Pi tracking main every five minutes means every unfinished commit is a production release. Deploying a tag means someone has to declare a build good; the Pi becomes a deliberate target. This would have contained the blast radius even if the bad code had been merged.
A fourth, smaller habit: keep the migration and the model change in one commit, since they are one logical change and only make sense together.
3. The neighbouring school wants a copy of the app. Explain the licence implications of the GPL-3.0 QR library and recommend what the team should do.
Read the worked answer
The GPL is a copyleft licence, and copyleft is triggered by distribution (the licence says "conveying"), not by use. Running the app inside the students' own school is not distribution, so the current use is unproblematic.
Giving a copy to another school is distribution. The QR library is linked into the same program, so the combined work is a derivative, and GPL-3.0 requires that recipients get the whole work under GPL-3.0 together with the corresponding source, including the students' own Python and templates. They cannot hand over a binary-only or proprietary copy of an app that links that library.
Three realistic options:
- Comply. Publish the source under GPL-3.0 and give the other school the source with the app. For a school project this is usually harmless - there is no commercial secret - but it is a decision, not a default, and it applies to everything in the repository.
- Replace the library with one under a permissive licence (MIT, BSD, Apache-2.0) or write a short QR encoder. This keeps the app under whatever licence the team prefers and is the cleanest option if they ever want to reuse it.
- Ask before assuming. The teacher should confirm the licence of every dependency (
pip-licensesor the repository'sLICENSEfiles) rather than only the one they remember.
Note the asymmetry: picking a permissive library now costs an afternoon; unwinding a copyleft obligation after distributing to twenty schools does not.