Grade an exercise chayneux / java_aop_training #1159
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Grade an exercise | |
run-name: Grade an exercise ${{ inputs.student-login }} / ${{ inputs.student-repo }} | |
on: | |
workflow_dispatch: | |
inputs: | |
grader-repo: | |
required: true | |
description: Grader repository to checkout first | |
student-login: | |
required: true | |
description: GitHub login of the student to grade | |
student-repo: | |
required: true | |
description: Name of the repository to grade | |
java-version: | |
description: Version of Java to setup before running the grader | |
default: '21' | |
callback-url: | |
required: true | |
description: URL to send events to | |
task-id: | |
required: true | |
description: Unique identifier of the running task | |
permissions: | |
contents: read | |
id-token: write | |
env: | |
REPORT_PATH: /tmp/results.json | |
METADATA_PATH: /tmp/metadata.json | |
jobs: | |
grade: | |
runs-on: ubuntu-latest | |
steps: | |
- name: ποΈ Generate Korekto app token | |
id: korekto-token | |
uses: getsentry/action-github-app-token@v3 | |
with: | |
app_id: ${{ vars.KOREKTO_APP_ID }} | |
private_key: ${{ secrets.KOREKTO_APP_PRIVATE_KEY }} | |
scope: ${{ inputs.student-login }} | |
- name: Gather student metadata | |
env: | |
STUDENT_LOGIN: ${{ inputs.student-login }} | |
STUDENT_REPO: ${{ inputs.student-repo }} | |
GH_TOKEN: ${{ steps.korekto-token.outputs.token }} | |
run: | | |
gh api "https://api.github.com/repos/$STUDENT_LOGIN/$STUDENT_REPO/commits/main" \ | |
| jq '{commit_id: .sha, short_commit_id: .sha[:7], commit_url: .html_url}' > $METADATA_PATH | |
- name: π’ Send STARTED event | |
uses: actions/github-script@v7 | |
env: | |
CALLBACK_URL: ${{ inputs.callback-url }} | |
STUDENT_LOGIN: ${{ inputs.student-login }} | |
GRADER_REPO: ${{ inputs.grader-repo }} | |
TASK_ID: ${{ inputs.task-id }} | |
with: | |
script: | | |
const fs = require('fs'); | |
const token = await core.getIDToken(); | |
const { | |
CALLBACK_URL, | |
STUDENT_LOGIN, | |
GRADER_REPO, | |
TASK_ID, | |
METADATA_PATH | |
} = process.env; | |
const metadata = JSON.parse(fs.readFileSync(METADATA_PATH)); | |
const payload = JSON.stringify({ | |
status: 'started', | |
student_login: STUDENT_LOGIN, | |
grader_repo: GRADER_REPO, | |
task_id: TASK_ID, | |
full_log_url: `https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}`, | |
metadata: metadata | |
}, null, 2); | |
console.log(`Sending ${payload}`); | |
const response = await fetch(CALLBACK_URL, { | |
method: 'POST', | |
body: payload, | |
headers: { | |
'Authorization': `bearer ${token}`, | |
'Content-type': "application/json; charset=UTF-8" | |
} | |
}); | |
if (!response.ok) { | |
const responseBody = await response.text(); | |
core.setFailed(`β Error sending start event: ${response.status} - ${responseBody}`); | |
} else { | |
core.info(`β Successfully sent start event: ${response.status} - ${response.statusText}`); | |
} | |
- name: β¬οΈ Checkout Grader | |
uses: actions/checkout@v4 | |
with: | |
repository: ${{ inputs.grader-repo }} | |
- name: β¨οΈ Setup Java ${{ inputs.java-version }} | |
uses: actions/setup-java@v4 | |
with: | |
distribution: temurin | |
java-version: ${{ inputs.java-version }} | |
cache: maven | |
- name: π― Grade, hoping for the best! | |
run: | | |
mvn compile exec:java -Dexec.args="-s=$STUDENT_LOGIN -r=$REPORT_PATH" -Dgithub_token="$KOREKTO_TOKEN" | |
env: | |
STUDENT_LOGIN: ${{ inputs.student-login }} | |
KOREKTO_TOKEN: ${{ steps.korekto-token.outputs.token }} | |
- name: π¬ Send result to server | |
uses: actions/github-script@v7 | |
env: | |
CALLBACK_URL: ${{ inputs.callback-url }} | |
OIDC_TOKEN: ${{ steps.oidc-token.outputs.result }} | |
STUDENT_LOGIN: ${{ inputs.student-login }} | |
GRADER_REPO: ${{ inputs.grader-repo }} | |
TASK_ID: ${{ inputs.task-id }} | |
with: | |
script: | | |
const fs = require('fs'); | |
const { | |
CALLBACK_URL, | |
OIDC_TOKEN, | |
STUDENT_LOGIN, | |
GRADER_REPO, | |
TASK_ID, | |
METADATA_PATH, | |
REPORT_PATH | |
} = process.env; | |
const metadata = JSON.parse(fs.readFileSync(METADATA_PATH)); | |
const result = JSON.parse(fs.readFileSync(REPORT_PATH)); | |
const token = await core.getIDToken(); | |
const response = await fetch(CALLBACK_URL, { | |
method: 'POST', | |
body: JSON.stringify({ | |
status: 'completed', | |
student_login: STUDENT_LOGIN, | |
grader_repo: GRADER_REPO, | |
task_id: TASK_ID, | |
full_log_url: `https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}`, | |
metadata: metadata, | |
details: result.details | |
}), | |
headers: { | |
'Authorization': `bearer ${token}`, | |
'Content-type': "application/json; charset=UTF-8" | |
} | |
}); | |
if (!response.ok) { | |
const responseBody = await response.text(); | |
core.setFailed(`β Error sending completed event: ${response.status} - ${responseBody}`); | |
} else { | |
core.info(`β Successfully sent completed event: ${response.status} - ${response.statusText}`); | |
} | |
- name: β Send job failure to server | |
if: ${{ failure() }} | |
uses: actions/github-script@v7 | |
env: | |
CALLBACK_URL: ${{ inputs.callback-url }} | |
OIDC_TOKEN: ${{ steps.oidc-token.outputs.result }} | |
STUDENT_LOGIN: ${{ inputs.student-login }} | |
GRADER_REPO: ${{ inputs.grader-repo }} | |
TASK_ID: ${{ inputs.task-id }} | |
with: | |
script: | | |
const fs = require('fs'); | |
const { | |
CALLBACK_URL, | |
OIDC_TOKEN, | |
STUDENT_LOGIN, | |
GRADER_REPO, | |
TASK_ID, | |
METADATA_PATH | |
} = process.env; | |
const getMetadata = () => { | |
try { | |
return JSON.parse(fs.readFileSync(METADATA_PATH)); | |
} catch (error) { | |
return { | |
commit_id: '<unknown>', | |
short_commit_id: '<unknown>', | |
commit_url: '<unknown>' | |
} | |
} | |
}; | |
const metadata = getMetadata(); | |
const obj_body = { | |
status: 'failure', | |
student_login: STUDENT_LOGIN, | |
grader_repo: GRADER_REPO, | |
task_id: TASK_ID, | |
full_log_url: `https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}`, | |
metadata: metadata | |
}; | |
console.log(JSON.stringify(obj_body, null, 2)); | |
const token = await core.getIDToken(); | |
const response = await fetch(CALLBACK_URL, { | |
method: 'POST', | |
body: JSON.stringify(obj_body), | |
headers: { | |
'Authorization': `bearer ${token}`, | |
'Content-type': "application/json; charset=UTF-8" | |
} | |
}); | |
if (!response.ok) { | |
const responseBody = await response.text(); | |
core.setFailed(`β Error sending failure event: ${response.status} - ${responseBody}`); | |
} else { | |
core.info(`β Successfully sent failure event: ${response.status} - ${response.statusText}`); | |
} |