From ba8196d574dd797fce3012f844a9768d5376f5fa Mon Sep 17 00:00:00 2001 From: Lasse Benninga Date: Fri, 17 Jul 2026 11:48:06 +0200 Subject: [PATCH] fix(ci): grant contents:read so grader runs + align autograder with rubric 1. .github/workflows/grade-assignment.yml: add 'contents: read' to the job permissions. The reusable auto-grade.yml requests contents:read (its actions/checkout needs it); a reusable workflow cannot request a permission the caller did not grant, so every run was startup_failure and no grader comment ever posted. Week 10's working workflow already has it. 2. .hyf/test.sh Level 3: accept psycopg2/psycopg imports, not just sqlalchemy. The rubric allows 'sqlalchemy or psycopg2'; the grader only credited sqlalchemy, under-scoring a valid psycopg2 submission by 5 pts. 3. .hyf/test.sh Level 4: count any H3 heading as a documented panel instead of only '### Panel'. A student who titles entries by metric name rather than 'Panel N' was scored 0 panels despite documenting them. Verified: no regression on a passing submission (95 -> 95); a psycopg2 app now gets the import point; panels titled by metric name are counted. --- .github/workflows/grade-assignment.yml | 1 + .hyf/test.sh | 10 ++++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/grade-assignment.yml b/.github/workflows/grade-assignment.yml index d06dc2d..3fd4b9c 100644 --- a/.github/workflows/grade-assignment.yml +++ b/.github/workflows/grade-assignment.yml @@ -8,6 +8,7 @@ on: jobs: grade: permissions: + contents: read issues: write pull-requests: write uses: HackYourFuture/github-actions/.github/workflows/auto-grade.yml@main diff --git a/.hyf/test.sh b/.hyf/test.sh index 769c8d9..6381454 100755 --- a/.hyf/test.sh +++ b/.hyf/test.sh @@ -88,10 +88,10 @@ pass "Level 2: secrets hygiene ($l2/15 pts)" # ── Level 3 (25 pts): Streamlit app content ───────────────────────────────── l3=0 if [[ -f "$app" ]]; then - if pygrep "^import sqlalchemy|^from sqlalchemy" "$app"; then - l3=$((l3 + 5)); pass "app.py: imports sqlalchemy" + if pygrep "^import sqlalchemy|^from sqlalchemy|^import psycopg|^from psycopg" "$app"; then + l3=$((l3 + 5)); pass "app.py: imports a Postgres driver (sqlalchemy or psycopg2)" else - fail "app.py: no sqlalchemy import found" + fail "app.py: no sqlalchemy or psycopg2 import found" fi if pygrep "os\.environ|os\.getenv" "$app"; then @@ -146,7 +146,9 @@ if file_has_content "$defs"; then l4=$((l4 + 5)); warn "metric_definitions.md: only $fields_ok/5 fields found" fi - panel_count=$(grep -cE "^### Panel" "$defs" 2>/dev/null || true) + # Count any H3 heading as a documented panel, so students who title + # entries by metric name rather than "Panel N" still get credit. + panel_count=$(grep -cE "^### " "$defs" 2>/dev/null || true) if [[ "$panel_count" -ge 4 ]]; then l4=$((l4 + 10)); pass "metric_definitions.md: $panel_count panels documented (>=4 expected: 3 Metabase + 1 Streamlit)" elif [[ "$panel_count" -ge 2 ]]; then