-
Notifications
You must be signed in to change notification settings - Fork 29
GitHub Integration
Every place Classroom 50 touches GitHub: what you do manually, what the CLI handles, and the REST API calls the tooling makes.
The CLI never creates the organization. Before running any CLI command:
-
Create the organization at https://github.com/account/organizations/new.
Free organizations work for public templates; Team or Enterprise Cloud is
required for Pages from the private
classroom50repository. - Flag your template repositories. On each template repository's Settings page, under General, select Template repository.
Note
A private template must live inside your organization; see Template visibility.
gh teacher init locks organization member privileges to least-privilege
automatically. After it runs, a member can only create a private repository
(so gh student accept works), publish a public Pages site (so the
classroom50 repository's assignments.json stays reachable), and create
teams (so students can form their own groups).
Why broad access to their own repository is safe for students
The lockdown denies the dangerous organization-wide powers (private Pages,
repository deletion and transfer, visibility changes, issue deletion,
dependency insights, member-invited outside collaborators). Two member
privileges stay deliberately on: public-repository creation is locked off only
on Enterprise Cloud, because Team and Free couple public and private creation
and the student flow needs private creation; and team creation stays on
because a student-formed group assignment has its founding student create the
group's team. So it's safe for gh student accept to grant broad access to a
student's own repository: individual students are downgraded to write
after creation, a legacy group founder keeps admin to add teammates (the
current group mode grants push through the group's GitHub Team instead), and
the organization locks defang the rest.
Four member-privilege settings have no API, so init can't set them and
audit can't read them. Apply them once by hand; the checklist is in
Manual organization hardening
in the CLI Teacher Guide.
Run once per machine, or after a token rotation:
gh teacher loginThis wraps gh auth login -s admin:org -s read:org -s repo -s workflow, the
unified Classroom 50 scope set, shared with gh student login, so
authenticating one CLI covers the other. (delete_repo is not included; opt
in with gh teacher login -s delete_repo for teardown.)
You often don't need to run it. Every other command checks your existing gh
credentials first: a sufficiently-scoped token is reused untouched, and an
under-scoped token that gh manages is widened in place with gh auth refresh
(your token is kept). login itself always re-runs gh auth login, which
replaces your stored github.com token, so when one already exists, the CLI
warns and asks for confirmation before proceeding. See
Will gh teacher login disturb my existing gh setup?.
| Scope | Required for |
|---|---|
admin:org |
Organization invitations, reading and removing memberships, managing teams (implies read:org). |
read:org |
Checking organization membership. |
repo |
Repository creation, contents writes, collaborators. |
workflow |
Committing the classroom50 repository's workflow files during init (GitHub 404s the write without it). |
Note
Tearing down an organization needs an extra permission. Signing in does
not request delete_repo. Exactly one feature needs it: Tear down
organization, in the organization's settings under Danger zone. It
resets an organization by deleting every repository in it, not only the
ones Classroom 50 created. When you use it, Classroom 50 asks you to request
that permission and sign in again, and teardown still runs only after you type
an explicit confirmation. Nothing else deletes repositories. Classroom 50 has
no server: the token stays in your browser, so nobody but you can act on your
organization with it. The CLIs work the same way: they never request
delete_repo unless you opt in with gh teacher login -s delete_repo.
If you signed in with a personal access token, Classroom 50 can't add the
permission for you: a token's permissions are fixed when you create it on
GitHub. Create one that allows deleting repositories (the delete_repo scope
on a classic token, or Administration: read and write on a fine-grained
one) and sign in again.
gh student loginSame device flow and the same scope set, so a student who authenticated a
teacher CLI (or the other way around) needs no re-auth. A student exercises
read:org (accept organization membership), repo (generate repositories,
collaborators), and workflow (commit the autograde workflow at accept).
gh teacher init uploads a PAT into the CLASSROOM50_SERVICE_TOKEN secret; the
score-collection, regrade, and token-probe workflows (collect-scores.yaml,
regrade.yaml, probe-token.yaml) use it to read student repositories across
the organization.
Create it at https://github.com/settings/personal-access-tokens/new from your own account (scope it tightly to the organization):
| Setting | Value |
|---|---|
| Resource owner | Your teaching organization. |
| Repository access | All repositories ("Only select repositories" misses on-demand student repositories). |
| Contents |
Read and write (read: collect; write: regrade pushes submit/* tags). |
| Actions | Read and write (regrade re-runs autograde). |
| Administration | Read and write (grant staff teams read on student repositories and templates). |
| Metadata | Read (auto-included; lets collection read legacy group repository collaborators). |
| Organization permissions, Members | Read (list the classroom team; a separate section, shown only once the organization is the resource owner). |
| Expiry | Up to 1 year; set a rotation reminder. |
Important
Members: Read is under Organization permissions, not Repository permissions, and isn't implied by any repository scope. A Contents-only token passes a Contents check but fails the first call collection makes.
Group assignments need no extra permission. Collection reads a group team's members with the same Members: Read the classroom team uses, and reads a legacy group repository's collaborators with Metadata: Read (auto-included), crediting members on the classroom team either way. A failed legacy read still scores the owner with a warning; a failed group-team read skips the repository and preserves its previous credit.
Supply the token in the environment variable, never as a flag (command-line PATs leak into shell history):
CLASSROOM50_SERVICE_TOKEN=github_pat_... gh teacher init YOUR-ORGANIZATIONReplace YOUR-ORGANIZATION with your organization's name. The token is
validated, encrypted with libsodium before upload, and never written to disk.
Rotate with gh teacher rotate-service-token YOUR-ORGANIZATION. In the web
app, the Service token section of the organization settings page builds
the same token with these permissions pre-filled.
init enables Pages and sets visibility to public. The first deployment needs
the publish-pages.yaml workflow to run once: push to the default branch or
trigger it from the Actions tab. The CLI prints the Pages URL
(https://YOUR-ORGANIZATION.github.io/classroom50/) after init.
If the organization's Pages site uses a custom domain, GitHub answers
github.io requests with a redirect that students' browsers reject. Set the
classroom's Custom Pages domain in the web app so browsers fetch from the
custom domain directly; server-side readers (the CLIs and Actions workflows)
follow the redirect and are unaffected. See
Using a custom Pages domain.
An assignment's GitHub Pages setting (web form, or gh teacher assignment add --pages) makes each accept configure a Pages site on the student's new
repository with POST /repos/{owner}/{repo}/pages, before the setup commit,
so students never need admin access to publish. GitHub Actions sets
build_type: workflow (a workflow in the student repository, from the
template or added by the student, deploys the site; it needs pages: write
and id-token: write permissions and uses actions/upload-pages-artifact and
actions/deploy-pages); A branch sets
build_type: legacy with the branch and folder. What GitHub requires:
- Plan: Pages on a private repository is available on GitHub Team, Enterprise Cloud, and Enterprise Server. On GitHub Free for organizations, only public repositories can have a site, so pair the setting with a Public repository visibility.
-
Organization policy: members must be allowed to publish Pages sites.
initturns on Pages creation (public) because theclassroom50repository needs it;gh teacher auditconfirms it. - Site visibility: a private repository's site is private (visible only to people with repository access) on plans that support it; a public repository's site is public.
Accept never fails on a refusal: the student sees why, and the teacher can
enable the site later from the submissions page (per repository or Enable
GitHub Pages for the whole assignment). Each site lives at
https://YOUR-ORGANIZATION.github.io/<repo>/; an organization with an
organization-wide custom Pages domain serves it under that domain as well.
init also turns on the organization's Allow GitHub Actions to create and
approve pull requests setting (the feedback pull request is opened by each
student repository's workflow) and opens the classroom50 repository's
reusable workflows to the organization. If init warns that an enterprise
policy blocked either, apply them yourself or ask your enterprise
administrator:
gh api -X PUT /orgs/YOUR-ORGANIZATION/actions/permissions/workflow \
-F default_workflow_permissions=write -F can_approve_pull_request_reviews=true
gh api -X PUT /repos/YOUR-ORGANIZATION/classroom50/actions/permissions/access \
-f access_level=organizationTrigger the collect-scores.yaml workflow from the Actions tab, optionally
scoped to one classroom or a single assignment (the same scoped runs the web
app dispatches: Collect all on a classroom's assignments list sends the
classroom-only scope, and the per-assignment Collect now sends both inputs):
gh workflow run collect-scores.yaml --repo YOUR-ORGANIZATION/classroom50
gh workflow run collect-scores.yaml --repo YOUR-ORGANIZATION/classroom50 -f classroom=CLASSROOM-SHORT-NAME
gh workflow run collect-scores.yaml --repo YOUR-ORGANIZATION/classroom50 -f classroom=CLASSROOM-SHORT-NAME -f assignment=ASSIGNMENT-SLUGReplace CLASSROOM-SHORT-NAME with the classroom's short name and
ASSIGNMENT-SLUG with the assignment's slug. A scoped run walks only the
matching repositories (one classroom's, or a single assignment's, which is
faster and cheaper on API rate limits for a large classroom) and stamps each
walked assignment's collected_at in scores.json; buckets outside the scope
are untouched. The staff-team read grant that rides along with collection is
scoped the same way, so a per-assignment run touches only that assignment's
repositories and template.
After init or rotate-service-token, or when collect or regrade returns 401
or 403, run the read-only probe. In the web app, open the organization settings
page and click Test token in the Service token section; the result
shows in place. From the CLI:
gh workflow run probe-token.yaml --repo YOUR-ORGANIZATION/classroom50A green run confirms every permission; a red run's log names the missing one. The probe is side-effect free.
Classroom 50 has no server. Whatever you authorize is a GitHub token that lives
only in your browser (web app) or your local gh credential store (CLI), so
nobody but you can act on your account with it. Sign-in requests one scope set
for everyone, a deliberate simplicity choice, not a technical requirement.
Teachers and students share a single flow because one person can be both (a
teacher testing an assignment as a student, a TA who also takes the course), so
the app asks for the union of what any role might need rather than making you
declare a role up front. A student's grant is therefore broader than what a
student actually uses. Capabilities are gated after sign-in by your role in the
organization and classroom, not by the scopes on your token.
The scopes below are GitHub's own. The table lists what each one grants across your whole account, why Classroom 50 needs it, and who actually exercises it.
| Scope | Access it grants | Why Classroom 50 needs it | Who uses it |
|---|---|---|---|
read:user |
Reads your public profile. | Identifies who you are after sign-in. | Everyone. |
read:org |
Reads your organization and team memberships. | Confirms membership and resolves your classroom role; a student accepts their own organization invitation. | Everyone. |
repo |
Full control of all your repositories: public and private, in every organization, not only the classroom one. GitHub offers no way to narrow it to a single organization. | Creating student repositories, committing configuration and setup files, reading scores (private-repository Releases), and managing repository collaborators. | Everyone. |
workflow |
Commit files under .github/workflows/ in repositories you can write. |
Landing the autograder workflow: teachers during init, students when the browser commits the autograde workflow on accept. |
Everyone (students only for default-autograder accepts). |
admin:org |
Administer organizations you own: invite and remove members, manage teams, change organization settings. | Inviting and removing students, managing classroom teams, and locking down organization policy. Implies read:org. |
Teachers only. |
delete_repo |
Permanently delete repositories. | Not requested at sign-in. One feature needs it, Tear down organization, and Classroom 50 asks for it on demand, then only after an explicit typed confirmation (see the teacher-authentication note above). | Teachers only, on demand. |
A student's flow only ever exercises three scopes: read:user (identify
themselves), read:org (accept their own organization invitation and read
their own memberships), and repo (generate their assignment repository, commit
their work, add a teammate as a collaborator on a legacy group repository, and
read their own scores). Default-autograder assignments also need workflow,
because the browser commits the autograde workflow file on accept; empty
repository and no-autograder assignments don't. That's the whole student
footprint.
A student never uses admin:org or delete_repo. Those are organization-owner
powers: a plain member's token can't perform them on an organization they don't
own, even though the shared grant nominally includes admin:org. The app
requests them because the sign-in flow is shared with teachers, not because a
student needs them. So the grant is broader than the footprint: the token can
touch all your repositories, but Classroom 50 only ever acts on classroom ones.
This matches the GitHub CLI's behavior, where gh teacher login and gh student login share one scope set for the same reason.
The one lever that actually narrows the grant is a fine-grained personal
access token, which is scoped to a single organization instead of your whole
account. On the sign-in card, click Other sign-in methods, then click Use a
personal access token (fine-grained); you name the organization (it becomes
the token's resource owner) and set Repository access to All repositories.
See If the proxy domain is blocked for the
full walkthrough. A classic OAuth sign-in can't be scoped this way (the repo
scope is all-or-nothing), so the fine-grained token is the tighter-security path
for anyone who wants to grant less. Why classic OAuth can't be scoped per
organization, and why sign-in doesn't ask you to pick a teacher or student role,
are recorded in Known Limitations.
If your school or district filters web traffic, allow the domains below so Classroom 50 works end to end. The web app runs entirely in the browser, so the browser itself must reach these hosts.
| Domain | Used by | For |
|---|---|---|
classroom50.org, preview.classroom50.org
|
Web app | Loading the app. |
classroom50.fifty-foundation.workers.dev |
Web app | The GitHub proxy (OAuth sign-in and repository downloads). See The GitHub proxy below. |
github.com |
Web app, CLI | OAuth sign-in and CLI authentication. |
api.github.com |
Web app, CLI, Actions | All GitHub REST API calls (classrooms, rosters, assignments, grading). |
*.github.io |
Web app, Actions | The organization's Pages site (YOUR-ORGANIZATION.github.io/classroom50/…): the assignment manifest, autograders, and the runner. If the organization's Pages site uses a custom domain, allow that domain too. See Using a custom Pages domain. |
codeload.github.com |
Web app | Repository archive (zip) downloads, reached through the proxy. |
www.githubstatus.com |
Web app | GitHub status check for the outage banner (best-effort). |
Two GitHub endpoints refuse cross-origin requests from a browser, so the web
app sends those two operations, and only those two, through a small proxy. It
defaults to the Fifty Foundation Cloudflare Worker at
classroom50.fifty-foundation.workers.dev:
- OAuth sign-in, both the browser redirect flow and the device-code flow. GitHub's token endpoint sends no CORS headers, and exchanging the login code for an access token needs the OAuth client secret, which can't be shipped in browser JavaScript. The proxy holds the secret and performs the exchange.
-
Repository downloads. GitHub's archive endpoint redirects to
codeload.github.com, which doesn't send the CORS headers a browser needs to follow the redirect. The proxy follows it server-side and streams the zip back.
The proxy is stateless: it keeps no copy of tokens or downloaded files, holds nothing between requests, and accepts requests only from the Classroom 50 web app's own origins. What passes through it:
| Operation | What the proxy handles |
|---|---|
| Sign-in | The one-time login code from GitHub and the access token GitHub returns for it. |
| Repository download | Your access token, used for that one request, and the zip archive as it streams to your browser. |
Both limits are GitHub's, not design choices, and the proxy exists only until
GitHub lifts them. Issue #877
tracks the workaround and the upstream work: the
single page app support for GitHub Apps
item on the GitHub roadmap would remove the sign-in half, and the download half
waits on CORS support for codeload.github.com
(octokit/rest.js#3).
The proxy is configurable: set VITE_GITHUB_PROXY_BASE at build time to point
the app at your own proxy instead of the default worker (the source is
cloudflare_worker.js).
Everything else the web app does talks to api.github.com directly and doesn't
involve the proxy, and the gh teacher and gh student CLIs never use it.
Some networks can't allow workers.dev. When the proxy is unreachable:
-
What still works: everything except the two operations above. All other
GitHub calls go straight to
api.github.com, so browsing classrooms, rosters, and assignments is unaffected. - What breaks: the normal Sign in with GitHub button and Use a device code instead (their token exchange goes through the proxy) and in-app repository downloads.
-
Signing in anyway: paste a personal access token instead. On the sign-in
card, click Other sign-in methods, then click Use a personal access
token (classic) or Use a personal access token (fine-grained). Both
validate the token directly against
api.github.com, so they never touch the proxy, and both link to a token-creation page with the required scopes or permissions pre-filled. A fine-grained token works with one organization only: you name the organization (it becomes the token's resource owner) and must set Repository access to All repositories. This sign-in token is one you paste into the web app; it is separate from the fine-grainedCLASSROOM50_SERVICE_TOKENused for score collection. -
A fuller fix: host the proxy yourself on a domain your network already
allows and point
VITE_GITHUB_PROXY_BASEat it. This restores both the normal sign-in and repository downloads.
Classroom 50 doesn't collect, store, or process student records. It has no server, database, or account system of its own, so there is no Classroom 50 data to request, export, or delete. Every classroom record (roster, assignment repositories, scores, feedback) lives in your GitHub organization under your organization's own access controls, and Classroom 50 acts on it only with a token you or your students grant. If your institution needs a data processing agreement, the party to that agreement is GitHub; see the GitHub Data Protection Agreement.
How each surface reaches GitHub:
| Surface | Where data goes |
|---|---|
| Web app | Your browser talks to api.github.com directly. Sign-in and repository downloads pass through the stateless proxy described in The GitHub proxy; signing in with a personal access token skips the proxy entirely. |
gh teacher and gh student
|
Your machine talks to GitHub directly. The CLIs never use the proxy. |
| Autograding and score collection | Run in GitHub Actions inside your organization, and results are stored in your organization's repositories. |
Classroom 50 can't make a course FERPA compliant on its own: compliance depends on how your institution and GitHub handle the data. What you can control is how much student data reaches GitHub in the first place:
- Pseudonymous accounts. Students don't need to give GitHub a real name or a school email. Let them use a pseudonym, and keep the mapping from pseudonym to student in your institution's own systems.
-
Roster contents. The roster holds only the columns you give it, and only a
GitHub username or id is required. Leave out names, and use
sectionlabels that don't identify anyone. Inviting by email sends that address to GitHub as an organization invitation. See Roster CSV fields. - A small teacher role. Organization owners can reach every repository. Keep that group small and use the head TA and TA roles for graders. See Staff, TAs, and Multiple Teachers.
- End-of-term cleanup. Archive or delete student repositories when the course ends. See End of term.
This section describes how Classroom 50 handles data; it isn't legal advice. Confirm your obligations with your institution's privacy office.
The CLIs call GitHub through go-gh; the
workflow scripts (collect_scores.py, regrade_repos.py, probe_token.py) use
urllib with a bearer token. The tables list the main endpoint families, not
every call.
| Method | Endpoint | Purpose |
|---|---|---|
| GET | /user |
Whoami. |
| GET | /orgs/{org} |
Check organization plan. |
| PATCH | /orgs/{org} |
Lock down member privileges at init. |
| GET / PUT | /orgs/{org}/actions/permissions |
Read and enable organization Actions. |
| GET / PUT | /orgs/{org}/actions/permissions/workflow |
Allow Actions to create pull requests (feedback pull requests). |
| GET / POST | /organizations/{org}/settings/billing/budgets |
Read and create the $0 Actions spending cap. |
| GET / POST / PUT | /orgs/{org}/rulesets |
Install the submission-history and feedback-base rulesets. |
| POST | /orgs/{org}/repos |
Create the classroom50 repository. |
| GET | /repos/{owner}/{repo} |
Check the classroom50 repository; validate a template. |
| POST / PUT | /repos/{owner}/{repo}/pages |
Enable Pages and set it public. |
| PUT | /repos/{owner}/{repo}/branches/{branch}/protection |
Protect the classroom50 repository's default branch. |
| GET / PUT | /repos/{owner}/{repo}/actions/permissions |
Read and re-enable Actions on the classroom50 repository. |
| GET / PUT | /repos/{owner}/{repo}/actions/permissions/workflow |
Read and set GITHUB_TOKEN permissions. |
| PUT | /repos/{owner}/{repo}/actions/permissions/access |
Allow same-organization reusable workflows. |
| GET / PUT | /repos/{owner}/{repo}/actions/secrets/... |
Upload the encrypted service PAT. |
| GET / POST / PATCH | /repos/{owner}/{repo}/git/{refs,commits,blobs,trees} |
Tree-commit configuration files (with rebase retry). |
| GET / POST / PATCH / DELETE |
/orgs/{org}/teams, /orgs/{org}/teams/{slug}
|
Create, read, update, and delete classroom, staff, invite, and group teams. |
| GET / PUT / DELETE |
/orgs/{org}/teams/{slug}/members, /orgs/{org}/teams/{slug}/memberships/{username}
|
Team membership (enrollment, staff roles, groups). |
| PUT / DELETE | /orgs/{org}/teams/{slug}/repos/{owner}/{repo} |
Grant staff teams the classroom50 repository and grant the classroom team a private template. |
| GET | /users/{username} |
Resolve a login to its numeric ID. |
| GET / POST / DELETE |
/orgs/{org}/invitations, /orgs/{org}/invitations/{id}
|
Send, list, and cancel organization invitations (email invitations carry teams). |
| GET / DELETE | /orgs/{org}/memberships/{username} |
Check and remove organization membership. |
| PUT / DELETE | /repos/{owner}/{repo}/collaborators/{username} |
Add and remove a repository collaborator. |
| GET / POST |
/repos/{owner}/{repo}/pulls, /repos/{owner}/{repo}/labels
|
Open or repair a feedback pull request (assignment feedback-pr). |
| DELETE | /repos/{owner}/{repo} |
Delete a repository (teardown; needs delete_repo). |
| GET |
/repos/{owner}/{repo}/releases + /releases/assets/{id}
|
Collect submit/* releases and result.json. |
| GET | /orgs/{org}/repos |
Page organization repositories for --by-pattern download and teardown. |
| Method | Endpoint | Purpose |
|---|---|---|
| GET | /user |
Whoami and git identity. |
| GET / PATCH | /user/memberships/orgs/{org} |
Check and accept a pending organization invitation. |
| POST | /repos/{template_owner}/{template_repo}/generate |
Generate the repository from a template (with include_all_branches when the assignment sets it). |
| POST | /orgs/{org}/repos |
Create the repository directly (template-less accept). |
| GET / PATCH | /repos/{owner}/{repo} |
Recover from "already exists"; read the template's features and apply the assignment's repository-feature settings (inherit, on, or off). |
| PUT | /repos/{owner}/{repo}/collaborators/{username} |
Set the founder role: push (individual) or admin (legacy group); also backs gh student invite. |
| GET / POST / PUT |
/user/teams, /orgs/{org}/teams, /orgs/{org}/teams/{slug}/memberships/{username}, /orgs/{org}/teams/{slug}/repos/{owner}/{repo}
|
Group assignments: find your group, found one (--new-team), add teammates, and attach the team to the shared repository. |
| GET / POST / PATCH |
/repos/{owner}/{repo}/git/{refs,commits,blobs,trees} + /branches/{branch}
|
Commit the setup files and freeze the feedback base branch. |
| GET / POST |
/repos/{owner}/{repo}/pulls, /repos/{owner}/{repo}/labels
|
Open the feedback pull request at accept. |
| POST | /repos/{owner}/{repo}/pages |
Configure the assignment's GitHub Pages site on the new repository (when the assignment sets pages). |
| GET | /repos/{owner}/{repo}/contents/{path} |
Fetch .gitignore and .github/ from the template (submit), and the template's pull request template. |
| Method | Endpoint | Purpose | FG-PAT permission |
|---|---|---|---|
| GET | /orgs/{org}/teams/{slug}/members |
List the classroom and staff teams (team-driven enrollment) and a group assignment's group teams. | Members: Read |
| GET | /orgs/{org}/repos |
List the organization's repositories once, to find accepted repositories and pushes without a release. | Metadata: Read |
| GET |
/repos/{owner}/{repo}/releases + /releases/assets/{id}
|
Collect submissions and result.json. |
Contents: Read |
| GET | /repos/{owner}/{repo}/collaborators |
Fan a legacy group score to teammates. | Metadata: Read |
| GET / PUT | /orgs/{org}/teams/{slug}/repos/{owner}/{repo} |
Grant staff teams read on student repositories and templates. | Administration: Read and write |
Exercises every permission with read-only calls GitHub gates behind the write
permission: /orgs/{org}/members, /orgs/{org}/teams/{slug}/members,
/repos/{org}/classroom50 (its permissions.push and permissions.admin),
/repos/{org}/classroom50/actions/permissions, and
/repos/{org}/classroom50/collaborators.
Jobs: setup (create the submit tag, validate configuration), grade (run
runner.py and the autograder, post status, publish the Release, maintain the
feedback pull request), and set-latest (serialized latest-pointer update). It
posts /repos/{owner}/{repo}/statuses/{sha}, uses git tag, git push, and
gh release for tags and Releases, and fetches unauthenticated from Pages:
| Endpoint | Purpose |
|---|---|
https://{org}.github.io/classroom50/{classroom}/assignments.json |
The assignment manifest and runtime block. |
https://{org}.github.io/classroom50/runner.py |
The runner bootstrap (organization-level). |
https://{org}.github.io/classroom50/ensure_feedback_pr.py |
The feedback pull request script (organization-level). |
https://{org}.github.io/classroom50/{classroom}/autograder.py |
The classroom default (a 404 means a vacuous pass). |
https://{org}.github.io/classroom50/{classroom}/autograders/{slug}.tar.gz |
The per-assignment bundle. |
For an unlisted classroom, {classroom} becomes {classroom}/{key}.
| File | Triggers | Purpose |
|---|---|---|
publish-pages.yaml |
Push to the default branch (roster-only commits skipped), workflow_dispatch
|
Deploy classrooms-index.json, each classroom's classroom.json and assignments.json, autograders and bundles, runner.py, and ensure_feedback_pr.py to Pages. |
collect-scores.yaml |
workflow_dispatch |
Aggregate result.json into */scores.json. |
regrade.yaml |
workflow_dispatch |
Push regrade tags to student repositories for an assignment. |
probe-token.yaml |
workflow_dispatch |
Read-only service-token permission check. |
autograde-runner.yaml (reusable) |
Called by each student's autograde.yaml
|
Grade, publish, update the latest pointer. |
| Variable / Secret | Set by | Used by | Purpose |
|---|---|---|---|
CLASSROOM50_SERVICE_TOKEN |
gh teacher init or the web app |
collect-scores.yaml, regrade.yaml, probe-token.yaml
|
Read student repository releases; regrade; probe the token. |
CLASSROOM50_SERVICE_TOKEN_EXPIRES_AT, CLASSROOM50_SERVICE_TOKEN_NAME
|
The web app (Actions variables) | The web app | Show the token's expiry countdown and display name. The CLI doesn't write them, so a CLI-provisioned token shows no tracked expiry. |
GITHUB_TOKEN |
Actions | Runner jobs | Tags, status, Release, feedback pull request. |
GH_DEBUG=api |
Developer | go-gh |
Log REST traffic. |
GITHUB_REPOSITORY_OWNER / GITHUB_API_URL
|
Actions | collect_scores.py |
Organization name and API base (supports Enterprise Server). |
The teacher and student CLIs read credentials from the gh auth store (populated
by gh teacher login and gh student login), not from GITHUB_TOKEN.
- Start here
- Teacher guides
- Autograding
- Students
- Reference