Initial commit #1
This file contains hidden or 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: GitHub Classroom Workflow | |
| on: | |
| push: | |
| branches: [main] | |
| permissions: | |
| checks: write | |
| actions: read | |
| contents: read | |
| pull-requests: write | |
| jobs: | |
| autograding: | |
| name: Autograding | |
| runs-on: ubuntu-latest | |
| outputs: | |
| grading_status: ${{ steps.grading.outcome }} | |
| steps: | |
| - uses: actions/setup-java@v5 | |
| with: | |
| distribution: 'temurin' | |
| java-version: '24' | |
| - uses: actions/checkout@v5 | |
| - name: Run autograder | |
| id: grading | |
| uses: education/autograding@v1 | |
| ai_feedback: | |
| name: AI-Powered Feedback | |
| needs: autograding | |
| if: ${{ needs.autograding.result == 'success' }} | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v5 | |
| # 🧠 Read instructions | |
| - name: Read assignment instructions | |
| id: instructions | |
| run: | | |
| echo "instructions=$(cat README.md | sed 's/\"/\\\"/g' | sed 's/$/\\n/' | tr -d '\n' | sed 's/\\n/\\\\n/g')" >> $GITHUB_OUTPUT | |
| # 📦 Read source code | |
| - name: Read source code | |
| id: source_code | |
| run: | | |
| { | |
| echo 'source_code<<EOF' | |
| find src/main/java -type f -name "*.java" | while read -r file; do | |
| echo "=== File: $file ===" | |
| cat "$file" | |
| echo | |
| done | |
| echo 'EOF' | |
| } >> "$GITHUB_OUTPUT" | |
| # 🧪 Read test code | |
| - name: Read test code | |
| id: test_code | |
| run: | | |
| { | |
| echo 'test_code<<EOF' | |
| if [ -d "src/test/java" ]; then | |
| find src/test/java -type f -name "*.java" | while read -r file; do | |
| echo "=== File: $file ===" | |
| cat "$file" | |
| echo | |
| done | |
| else | |
| echo "No test code found." | |
| fi | |
| echo 'EOF' | |
| } >> "$GITHUB_OUTPUT" | |
| # 🤖 Generate AI Feedback | |
| - name: Generate AI Feedback | |
| id: ai_feedback | |
| env: | |
| OPENROUTER_MODEL: ${{ vars.OPENROUTER_MODEL }} | |
| SYSTEM_PROMPT: ${{ vars.SYSTEM_PROMPT }} | |
| run: | | |
| INSTRUCTIONS=$(jq -Rs . <<'EOF' | |
| ${{ steps.instructions.outputs.instructions }} | |
| EOF | |
| ) | |
| SOURCE_CODE=$(jq -Rs . <<'EOF' | |
| ${{ steps.source_code.outputs.source_code }} | |
| EOF | |
| ) | |
| TEST_CODE=$(jq -Rs . <<'EOF' | |
| ${{ steps.test_code.outputs.test_code }} | |
| EOF | |
| ) | |
| if [ -z "$INSTRUCTIONS" ] || [ -z "$SOURCE_CODE" ] || [ -z "$TEST_CODE" ]; then | |
| echo "Error: One or more required variables are not set." | |
| exit 1 | |
| fi | |
| PAYLOAD="Please provide feedback on the following Java assignment.\n\n--- Assignment Instructions ---\n${INSTRUCTIONS}\n\n--- Source files ---\n${SOURCE_CODE}\n\n--- Test files ---\n${TEST_CODE}" | |
| JSON_CONTENT=$(jq -n \ | |
| --arg model "$OPENROUTER_MODEL" \ | |
| --arg system_prompt "$SYSTEM_PROMPT" \ | |
| --arg payload "$PAYLOAD" \ | |
| '{ | |
| models: $model, | |
| messages: [ | |
| {role: "system", content: $system_prompt}, | |
| {role: "user", content: $payload} | |
| ] | |
| }') | |
| API_RESPONSE=$(echo "$JSON_CONTENT" | curl https://openrouter.ai/api/v1/chat/completions \ | |
| -H "Authorization: Bearer ${{ secrets.OPENROUTER_API_KEY }}" \ | |
| -H "Content-Type: application/json" \ | |
| -d @-) | |
| FEEDBACK_CONTENT=$(echo "$API_RESPONSE" | jq -r '.choices[0].message.content') | |
| echo "feedback<<EOF" >> $GITHUB_OUTPUT | |
| echo "$FEEDBACK_CONTENT" >> $GITHUB_OUTPUT | |
| echo "EOF" >> $GITHUB_OUTPUT | |
| # 💬 Post Feedback | |
| - name: Post Feedback as PR Comment ✍️ | |
| uses: actions/github-script@v7 | |
| env: | |
| FEEDBACK_BODY: ${{ steps.ai_feedback.outputs.feedback }} | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| script: | | |
| const signature = ""; | |
| const body = `${process.env.FEEDBACK_BODY}\n\n${signature}`; | |
| const { owner, repo } = context.repo; | |
| const issue_number = context.issue.number; | |
| const { data: comments } = await github.rest.issues.listComments({ | |
| owner, | |
| repo, | |
| issue_number, | |
| }); | |
| const previousComment = comments.find(comment => comment.body.includes(signature)); | |
| if (previousComment) { | |
| await github.rest.issues.updateComment({ | |
| owner, | |
| repo, | |
| comment_id: previousComment.id, | |
| body, | |
| }); | |
| } else { | |
| await github.rest.issues.createComment({ | |
| owner, | |
| repo, | |
| issue_number, | |
| body, | |
| }); | |
| } |