11name : Create Department Evaluation
2+
23on :
34 push :
45 branches : ["submission-*"]
56
67jobs :
7- evaluate :
8+ evaluate_department :
89 runs-on : ubuntu-latest
910 env :
1011 CARE_API_BASE_URL : ${{ secrets.CARE_API_BASE_URL }}
1112 CARE_FE_BASE_URL : ${{ secrets.CARE_FE_BASE_URL }}
1213 steps :
13- - name : Checkout
14- uses : actions/checkout@v4
14+ - name : Checkout repository
15+ uses : actions/checkout@v6
1516 with :
1617 token : ${{ secrets.CARE_GITHUB_ACTION_TOKEN }}
1718
18- # ── Fetch setup_data.json from main branch ──
1919 - name : Fetch setup data from main
2020 id : setup
2121 run : |
@@ -24,17 +24,13 @@ jobs:
2424 USER_ID=$(jq -r '.user.id' setup_data.json)
2525 EXPECTED_FACILITY_ID=$(jq -r '.facility_management.facility_id // empty' setup_data.json)
2626
27- # Missing user.id is a course-config bug (bootstrap action didn't run) —
28- # not student-recoverable, so fail hard and surface in CI logs.
27+ # missing user.id: bootstrap did not run, not student-recoverable
2928 if [ -z "$USER_ID" ] || [ "$USER_ID" = "null" ]; then
3029 echo "::error::Could not read user.id from setup_data.json"
3130 exit 1
3231 fi
3332
34- # Missing facility_id IS student-recoverable: the previous target
35- # (Create Facility) hasn't been *passed* yet. Pupilfirst lets students
36- # submit this target after merely *submitting* the prerequisite, so we
37- # need to give actionable feedback here instead of failing the job.
33+ # missing facility_id: Create Facility hasn't passed yet, surface feedback
3834 if [ -z "$EXPECTED_FACILITY_ID" ] || [ "$EXPECTED_FACILITY_ID" = "null" ]; then
3935 FEEDBACK="Please pass the **Create Facility** target first. Submitting it isn't enough — it needs a passing grade so this evaluation can verify the department belongs to your facility."
4036 jq -n \
4844 echo "user_id=$USER_ID" >> $GITHUB_OUTPUT
4945 echo "expected_facility_id=$EXPECTED_FACILITY_ID" >> $GITHUB_OUTPUT
5046
51- # ── Single source of truth for the allowed department names ──
52- # Used by the jq filters (grading) and the human-readable feedback message.
5347 - name : Define allowed department names
5448 id : depts
5549 run : |
@@ -65,14 +59,13 @@ jobs:
6559 "Laboratory"
6660 "Emergency"
6761 )
68- # jq IN(...) argument list: "Cardiology","Neurology",...
62+ # formatted for jq IN()
6963 JQ_LIST=$(printf '%s\n' "${NAMES[@]}" | jq -R . | paste -sd, -)
70- # Human-readable list: Cardiology, Neurology, ...
64+ # formatted for feedback
7165 HUMAN=$(IFS=, ; printf '%s' "${NAMES[*]}" | sed 's/,/, /g')
7266 echo "jq_list=$JQ_LIST" >> $GITHUB_OUTPUT
7367 echo "human=$HUMAN" >> $GITHUB_OUTPUT
7468
75- # ── Parse department URL from submission ──
7669 - name : Parse submission data
7770 if : env.skip_checks != 'true'
7871 id : parse
9487 ;;
9588 esac
9689
97- # Extract facility_id and department_id from URL
9890 # URL format: <CARE_FE_BASE_URL>/facility/{facility_id}/settings/departments/{department_id}/departments
9991 UUID_RE='[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}'
10092
@@ -111,7 +103,6 @@ jobs:
111103 echo "department_id=$DEPARTMENT_ID" >> $GITHUB_OUTPUT
112104 echo "valid=true" >> $GITHUB_OUTPUT
113105
114- # ── Validate URL was parsed successfully ──
115106 - name : Validate parsed URL
116107 if : env.skip_checks != 'true' && steps.parse.outputs.valid != 'true'
117108 env :
@@ -127,7 +118,6 @@ jobs:
127118
128119 echo "skip_checks=true" >> $GITHUB_ENV
129120
130- # ── Validate the URL's facility_id matches the student's facility from the previous target ──
131121 - name : Validate facility ownership in URL
132122 if : env.skip_checks != 'true' && steps.parse.outputs.url_facility_id != steps.setup.outputs.expected_facility_id
133123 env :
@@ -144,7 +134,6 @@ jobs:
144134
145135 echo "skip_checks=true" >> $GITHUB_ENV
146136
147- # ── Single API call: check all 4 conditions ──
148137 - name : Check department requirements
149138 if : env.skip_checks != 'true'
150139 id : check
@@ -167,13 +156,13 @@ jobs:
167156 label : " All department requirements met"
168157 output-jq-filter : |
169158 {
159+ dept_name: (.name // ""),
170160 name: ((.name // "") | IN(${{ steps.depts.outputs.jq_list }})),
171161 type: (.org_type == "dept"),
172162 not_system: (.system_generated == false),
173163 creator: (.created_by.id == "${{ steps.setup.outputs.user_id }}")
174164 }
175165
176- # ── Build feedback from check results ──
177166 - name : Build feedback
178167 if : env.skip_checks != 'true'
179168 env :
@@ -182,7 +171,6 @@ jobs:
182171 PASSED : ${{ steps.check.outputs.passed }}
183172 ALLOWED_HUMAN : ${{ steps.depts.outputs.human }}
184173 run : |
185- # Differentiated message when the API call itself failed (e.g. 404)
186174 if echo "$RESULT" | grep -q '^error:'; then
187175 FEEDBACK=$(printf "Uh oh! We couldn't fetch your department from CARE.\n\nDetails: %s\n\nMake sure the department URL you submitted is correct and that the department hasn't been deleted. Expected URL format: \`%s/facility/<facility-id>/settings/departments/<department-id>/departments\`" \
188176 "$RESULT" "$CARE_FE_BASE_URL")
@@ -194,12 +182,12 @@ jobs:
194182 exit 0
195183 fi
196184
197- # Parse individual results
185+ # map results to check flags
198186 T1="✗"; T2="✗"; T3="✗"; T4="✗"
199- [ "$(echo "$RESULTS" | jq -r '.name')" = "true" ] && T1="✓"
200- [ "$(echo "$RESULTS" | jq -r '.type')" = "true" ] && T2="✓"
187+ [ "$(echo "$RESULTS" | jq -r '.name')" = "true" ] && T1="✓"
188+ [ "$(echo "$RESULTS" | jq -r '.type')" = "true" ] && T2="✓"
201189 [ "$(echo "$RESULTS" | jq -r '.not_system')" = "true" ] && T3="✓"
202- [ "$(echo "$RESULTS" | jq -r '.creator')" = "true" ] && T4="✓"
190+ [ "$(echo "$RESULTS" | jq -r '.creator')" = "true" ] && T4="✓"
203191
204192 if [ "$PASSED" = "true" ]; then
205193 HEADER="Great work! All checks passed. Your department meets all the requirements."
@@ -217,7 +205,40 @@ jobs:
217205 --arg feedback "$FEEDBACK" \
218206 '{status: $status, feedback: $feedback}' > report.json
219207
220- # ── Grade via grade-action ──
208+ - name : Persist department name to setup_data.json
209+ if : env.skip_checks != 'true' && steps.check.outputs.passed == 'true'
210+ env :
211+ EXTRACTED : ${{ steps.check.outputs.extracted }}
212+ SUBMISSION_ID : ${{ steps.parse.outputs.submission_id }}
213+ run : |
214+ DEPT_NAME=$(echo "$EXTRACTED" | jq -r '.dept_name')
215+
216+ # switch to main
217+ git fetch origin main
218+ git checkout -B main origin/main
219+
220+ # update setup_data.json
221+ jq --arg name "$DEPT_NAME" \
222+ '. as $root | (.facility_management // {}) as $fm
223+ | $root + {facility_management: ($fm + {department_name: $name})}' \
224+ setup_data.json > setup_data.json.tmp
225+ mv setup_data.json.tmp setup_data.json
226+
227+ if git diff --quiet setup_data.json; then
228+ echo "setup_data.json already up to date; nothing to commit."
229+ git checkout "$GITHUB_REF_NAME"
230+ exit 0
231+ fi
232+
233+ git config user.name "HMIS bot"
234+ git config user.email "hmiscare@gmail.com"
235+ git add setup_data.json
236+ git commit -m "chore(setup): record facility_management.department_name (submission $SUBMISSION_ID) [skip ci]"
237+ git push origin main
238+
239+ # restore submission branch
240+ git checkout "$GITHUB_REF_NAME"
241+
221242 - name : Grade submission
222243 if : always()
223244 uses : pupilfirst/grade-action@v1
@@ -227,7 +248,6 @@ jobs:
227248 REVIEW_END_POINT : ${{ secrets.PF_REVIEW_END_POINT }}
228249 REVIEW_BOT_USER_TOKEN : ${{ secrets.PF_REVIEW_BOT_USER_TOKEN }}
229250
230- # ── Report result to LMS ──
231251 - name : Report success to LMS
232252 if : success()
233253 uses : pupilfirst/report-action@v1
0 commit comments