You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: action.yml
+26Lines changed: 26 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -28,6 +28,26 @@ inputs:
28
28
description: 'Whether to include/generate feedback. Use "true" or "false". Defaults to false.'
29
29
required: false
30
30
default: "false"
31
+
execution-mode:
32
+
description: 'Execution mode for the autograder. Use "repo" (default) for repository-config mode or "external" to load config from the Autograder Cloud.'
33
+
required: false
34
+
default: "repo"
35
+
grading-config-id:
36
+
description: "The grading configuration ID from the Autograder Cloud. Required when execution-mode is \"external\"."
37
+
required: false
38
+
autograder-cloud-url:
39
+
description: "The base URL of the Autograder Cloud instance. Required when execution-mode is \"external\"."
40
+
required: false
41
+
autograder-cloud-token:
42
+
description: "Authentication token for the Autograder Cloud API. Required when execution-mode is \"external\"."
43
+
required: false
44
+
submission-language:
45
+
description: "Programming language of the student submission (e.g. 'python', 'java'). Validated against the grading config's supported languages. Defaults to the first language in the config when omitted. Only used in external mode."
46
+
required: false
47
+
locale:
48
+
description: "Locale for feedback messages (e.g. 'en', 'pt-br'). Defaults to 'en'."
Copy file name to clipboardExpand all lines: docs/API.md
+96Lines changed: 96 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -853,6 +853,102 @@ GET /api/v1/ready
853
853
854
854
---
855
855
856
+
## External Mode Integration
857
+
858
+
This section describes how the Autograder GitHub Action in **external mode** interacts with the API. The action makes exactly two authenticated calls per grading run.
859
+
860
+
### Integration sequence
861
+
862
+
```
863
+
1. GET /api/v1/configs/id/{grading_config_id} # fetch grading config
864
+
2. POST /api/v1/submissions/external-results # submit result (or failure)
865
+
```
866
+
867
+
Both endpoints require the `Authorization: Bearer <token>` header where the token matches `AUTOGRADER_INTEGRATION_TOKEN` on the server.
868
+
869
+
### Config fetch
870
+
871
+
```http
872
+
GET /api/v1/configs/id/{grading_config_id}
873
+
Authorization: Bearer <token>
874
+
```
875
+
876
+
Returns the full grading configuration object (see [Get Grading Configuration by Internal ID](#get-grading-configuration-by-internal-id)). The action uses the following fields from the response:
877
+
878
+
| Field | Used for |
879
+
|-------|----------|
880
+
|`id`| Sent back as `grading_config_id` in the result payload |
881
+
|`template_name`| Selects the grading template |
882
+
|`criteria_config`| Grading rubric |
883
+
|`languages`| Validates `submission-language`; defaults to `languages[0]` if omitted |
884
+
|`include_feedback`| Whether to run the feedback step |
885
+
|`setup_config`| Pre-flight setup commands and required files |
886
+
|`feedback_config`| Reporter configuration |
887
+
888
+
### Result submission (success)
889
+
890
+
```http
891
+
POST /api/v1/submissions/external-results
892
+
Authorization: Bearer <token>
893
+
Content-Type: application/json
894
+
895
+
{
896
+
"grading_config_id": 42,
897
+
"external_user_id": "github-actor-login",
898
+
"username": "github-actor-login",
899
+
"language": "python",
900
+
"status": "completed",
901
+
"final_score": 85.5,
902
+
"feedback": "## Grade: 85.5/100\n...",
903
+
"result_tree": { ... },
904
+
"focus": { ... },
905
+
"pipeline_execution": { ... },
906
+
"execution_time_ms": 3200,
907
+
"error_message": null,
908
+
"submission_metadata": {
909
+
"repository": "org/repo",
910
+
"commit_sha": "abc123",
911
+
"run_id": "999",
912
+
"actor": "student1",
913
+
"ref": "refs/heads/main"
914
+
}
915
+
}
916
+
```
917
+
918
+
### Result submission (failure)
919
+
920
+
When grading fails, the action posts a failure payload before exiting non-zero:
921
+
922
+
```json
923
+
{
924
+
"grading_config_id": 42,
925
+
"external_user_id": "github-actor-login",
926
+
"username": "github-actor-login",
927
+
"language": "python",
928
+
"status": "failed",
929
+
"final_score": 0.0,
930
+
"feedback": null,
931
+
"result_tree": null,
932
+
"focus": null,
933
+
"pipeline_execution": null,
934
+
"execution_time_ms": 1500,
935
+
"error_message": "Sandbox timed out after 30 s",
936
+
"submission_metadata": { ... }
937
+
}
938
+
```
939
+
940
+
### Error handling
941
+
942
+
| Scenario | Action behaviour |
943
+
|----------|-----------------|
944
+
|`401` on config fetch | Exits non-zero; no result posted |
945
+
|`404` on config fetch | Exits non-zero; no result posted |
946
+
| 5xx / network error on config fetch | Retries with exponential back-off; then exits non-zero |
Copy file name to clipboardExpand all lines: docs/github_action/README.md
+24-2Lines changed: 24 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,16 +4,33 @@ This module packages the Autograder as a Docker-based GitHub Action so repositor
4
4
5
5
It is primarily designed for GitHub Classroom style workflows, but can be used by any repository that follows the expected directory contract.
6
6
7
-
## What it does
7
+
## Execution modes
8
8
9
-
When a workflow runs:
9
+
| Mode | How config is loaded | When to use |
10
+
|------|---------------------|-------------|
11
+
|`repo` (default) | From config files checked out inside `submission/.github/autograder/`| Repository-based setups where grading config lives in the student repo |
12
+
|`external`| Fetched from the Autograder Cloud API at runtime | Centralised setups where a single Autograder Cloud instance manages all assignments |
13
+
14
+
## What it does (repo mode)
15
+
16
+
When a workflow runs in `repo` mode:
10
17
11
18
1. Reads student files from `submission/`.
12
19
2. Reads grading config from `submission/.github/autograder/`.
13
20
3. Builds and executes the Autograder pipeline.
14
21
4. Updates the GitHub check run with the final score.
15
22
5. Optionally commits `relatorio.md` with feedback.
16
23
24
+
## What it does (external mode)
25
+
26
+
When a workflow runs in `external` mode:
27
+
28
+
1. Fetches the grading configuration from the Autograder Cloud (`GET /api/v1/configs/id/{id}`).
29
+
2. Reads student files from `submission/`.
30
+
3. Builds and executes the Autograder pipeline.
31
+
4. Posts the grading result back to the Autograder Cloud (`POST /api/v1/submissions/external-results`).
32
+
5. If grading fails for any reason, posts a `failed` status payload before exiting non-zero.
|[`github_action/github_action_service.py`](https://github.com/webtech-network/autograder/blob/main/github_action/github_action_service.py)| Builds pipeline from JSON configs and handles GitHub export operations. |
26
43
|[`github_action/github_classroom_exporter.py`](https://github.com/webtech-network/autograder/blob/main/github_action/github_classroom_exporter.py)| Export adapter that reports score and feedback through `GithubActionService`. |
44
+
|[`github_action/cloud_client.py`](https://github.com/webtech-network/autograder/blob/main/github_action/cloud_client.py)| HTTP client for the Autograder Cloud API (config fetch + result submission). Uses exponential back-off on 5xx/network errors; raises `CloudClientError` on 4xx. |
45
+
|[`github_action/cloud_exporter.py`](https://github.com/webtech-network/autograder/blob/main/github_action/cloud_exporter.py)| Export adapter for external mode. Builds the `ExternalResultCreate` payload and calls `CloudClient`. Provides `submit_failure()` for the failure path. |
27
46
28
47
## Repository contract required by the Action
29
48
@@ -47,6 +66,8 @@ Inside that checkout, the Action expects:
47
66
- `feedback-type: ai` requires `openai-key`.
48
67
- The current notification logic looks for a check run named `grading`.
49
68
- `include-feedback: "true"` enables feedback generation and may update `relatorio.md`.
69
+
- In `external` mode, `include_feedback` is taken from the cloud config, **not** from the `include-feedback` action input.
70
+
- In `external` mode, `submission-language` is validated against the `languages` list in the cloud config. Omitting it defaults to the first language in that list.
50
71
51
72
## Reference repository
52
73
@@ -55,4 +76,5 @@ Use **[`webtech-network/demo-autograder`](https://github.com/webtech-network/dem
template-preset: "input_output"# required by the parser; value is ignored in external mode
67
+
```
68
+
36
69
## Inputs
37
70
38
71
From [`action.yml`](https://github.com/webtech-network/autograder/blob/main/action.yml):
39
72
40
73
| Input | Required | Default | Notes |
41
74
|---|---:|---|---|
42
75
| `github-token` | no | `${{ github.token }}` | Used for GitHub API operations (repo/check run access). |
43
-
| `template-preset` | yes | - | Template key used by the grading pipeline. Built-ins include `webdev`, `api`, and `input_output`. |
76
+
| `template-preset` | yes | - | Template key used by the grading pipeline. Built-ins include `webdev`, `api`, and `input_output`. In external mode the pipeline reads the template from the cloud config, but this field is still required by the parser. |
| `custom-template` | no | - | Currently not usable because `template-preset: custom` is rejected by `github_action/main.py`. |
46
79
| `openai-key` | no | - | Required only when `feedback-type` is `ai`. |
47
80
| `app-token` | no | - | Optional token for repository access; if omitted, runtime falls back to `github-token`. |
48
-
| `include-feedback` | no | `"false"` | Must be `"true"` or `"false"` string. Controls whether feedback step is included. |
81
+
| `include-feedback` | no | `"false"` | Must be `"true"` or `"false"` string. Ignored in external mode (value is taken from the cloud config). |
82
+
| `execution-mode` | no | `"repo"` | `"repo"` or `"external"`. Determines where grading configuration is loaded from. |
83
+
| `grading-config-id` | no | - | Internal DB id of the grading config on the Autograder Cloud. Required when `execution-mode` is `external`. |
84
+
| `autograder-cloud-url` | no | - | Base URL of the Autograder Cloud instance (e.g. `https://cloud.example.com`). Required when `execution-mode` is `external`. |
85
+
| `autograder-cloud-token` | no | - | Integration token for the Autograder Cloud API. Required when `execution-mode` is `external`. Should be stored as a repository secret. |
86
+
| `submission-language` | no | - | Language of the student submission (e.g. `python`, `java`). Validated against the cloud config's `languages` list. Defaults to the first language in the list when omitted. Only used in `external` mode. |
49
87
50
88
## Outputs
51
89
@@ -72,24 +110,41 @@ It also reads student files recursively from `submission/`, excluding `.git` and
72
110
73
111
## Secrets and permissions
74
112
75
-
### Typical secrets
113
+
### Repo mode secrets
76
114
77
115
- `ENGINE`(or another secret mapped to `openai-key`) when using AI feedback.
78
116
- Optional token secret mapped to `app-token` if you need separate credentials.
79
117
118
+
### External mode secrets
119
+
120
+
| Secret | Maps to input | Description |
121
+
|--------|--------------|-------------|
122
+
| `AUTOGRADER_CLOUD_URL` | `autograder-cloud-url` | Base URL of the Autograder Cloud instance |
123
+
| `AUTOGRADER_CLOUD_TOKEN` | `autograder-cloud-token` | Integration token (set `AUTOGRADER_INTEGRATION_TOKEN` on the server) |
124
+
125
+
> Generate a strong token on the server: `openssl rand -hex 32`
126
+
80
127
### Permissions
81
128
82
-
`permissions: write-all` is commonly used because the Action may:
129
+
`permissions: write-all` is required in **repo mode** because the Action may:
83
130
84
131
- update the workflow check run with score summary;
85
132
- commit `relatorio.md` when feedback is enabled.
86
133
134
+
In **external mode**, no GitHub repository write operations are performed, so elevated permissions are not required.
135
+
87
136
## Troubleshooting
88
137
89
138
### `FileNotFoundError: criteria.json file not found`
90
139
91
140
- Ensure your workflow checks out repository to `path: submission`.
92
141
- Ensure config is at `submission/.github/autograder/criteria.json`.
142
+
- This error only occurs in **repo mode**; in external mode, config is fetched from the cloud.
143
+
144
+
### `grading-config-id`, `autograder-cloud-url`, or `autograder-cloud-token` missing
145
+
146
+
- All three are required when `execution-mode` is `external`.
147
+
- The entrypoint validates these before starting the pipeline and exits non-zero if any are absent.
93
148
94
149
### `OpenAI API key is required for AI feedback mode`
95
150
@@ -107,4 +162,5 @@ It also reads student files recursively from `submission/`, excluding `.git` and
0 commit comments